我怎样才能没有查找到AspNetUserRoles表的WebAPI方法内用户的角色? [英] How can I get a users role inside a WebAPI method without a lookup to the AspNetUserRoles table?

查看:1133
本文介绍了我怎样才能没有查找到AspNetUserRoles表的WebAPI方法内用户的角色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个存储过程,更新状态。根据用户的角色的存储过程有code,可能会或可能不会允许的状态的变化。出于这个原因,我需要一个角色名传递到存储过程。我的角色名称存储在客户端上我的javascript code,但我当然需要服务器上的第二次检查。每个用户只有三个角色之一,并请求的状态更新时,取决于客户有作用的三种方法之一,我可以打电话。下面是我试过了。

I have a stored procedure that updates status. Depending on the role of the user the stored procedure has code that may or may not allow the status change. For this reason I need to pass a role name into a stored procedure. My role name is stored on the client in my javascript code but of course I need a second check on the server. Each user has only one of three roles and when requesting an update of status I can call one of three methods depending on the role that the client has. Here's what I tried.

我使用的我的WebAPI基于承载令牌认证和ASP.NET 2.1身份并应用始终运行在浏览器中。我的用户已经设置了相应的角色。

I am using WebApi with bearer Token based authentication and ASP.NET Identity 2.1 and the application always runs in a browser. My users have been set up with the appropriate roles.

我采取了一些code以获取用户标识,然后转到AspNetUserRoles表来获得在方法开始时的作用。不过,我注意到这个大约需要500毫秒才能运行。作为一种替代我正在考虑以下内容:

I put in place some code to get the userId and then go to the AspNetUserRoles table to get the role at the start of a method. However I noticed this takes around 500 milliseconds to run. As an alternative I am considering the following:

    [HttpPut]
    [Authorize(Roles = "Admin")]
    [Route("AdminUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
    public async Task<IHttpActionResult> AdminUpdateStatus(int userTestId, int userTestStatusId)
    {
        return await UpdateStatusMethod(userTestId, userTestStatusId, "Admin");
    }

    [HttpPut]
    [Authorize(Roles = "Student")]
    [Route("StudentUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
    public async Task<IHttpActionResult> StudentUpdateStatus(int userTestId, int userTestStatusId)
    {
        return await UpdateStatusMethod(userTestId, userTestStatusId, "Student");
    }

    [HttpPut]
    [Authorize(Roles = "Teacher")]
    [Route("TeacherUpdateStatus/{userTestId:int}/{userTestStatusId:int}")]
    public async Task<IHttpActionResult> TeacherUpdateStatus(int userTestId, int userTestStatusId)
    {
        return await UpdateStatusMethod(userTestId, userTestStatusId, "Teacher");
    }

    private async Task<IHttpActionResult> UpdateStatusMethod(int userTestId, int userTestStatusId, string roleName)
    {
        // Call the stored procedure here and pass in the roleName
    }

这是一种有效的方式做到这一点还是有可能是另一种更清洁的方式。如果前端或后端缓存用户的角色是什么,我就相当不明确的。我认为这样做还是有一些设置,将允许这种事情要做。

Is this an efficient way to do this or is there perhaps another more clean way. What I am rather unclear on is if the front or back end caches the users role. I assume that this is done or there is some setting that will allow this to be done.

请注意我用的索赔角色信息发送到我的客户在这里:

Note I am using claims to send the Role information to my client here:

public static AuthenticationProperties CreateProperties(
            string userName,
            ClaimsIdentity oAuthIdentity,
            string firstName,
            string lastName,
            int organization)
        {
            IDictionary<string, string> data = new Dictionary<string, string>
                {
                    { "userName", userName},
                    { "firstName", firstName},
                    { "lastName", lastName},
                    { "organization", organization.ToString()},
                    { "roles",string.Join(":",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}

                };
            return new AuthenticationProperties(data);
        }

不过在这里我的问题涉及到服务器,我怎么能在我的方法检查,如果用户是有一定的作用,而不去到数据库中。也许有办法与安全要求这样做,但我不知道该怎么做。

However my question here relates to the server and how I can check in my method if a user is in a certain role without going to the database. Maybe there's a way to do this securely with claims but I don't know how to do that.

任何帮助和建议会更AP preciated。

Any help and advice would be much appreciated.

推荐答案

当你说你正在使用承载令牌来保护你的终点。我认为,有一点小误会什么那些承载令牌神奇的字符串包含在里面。
那么这些令牌包含您发出的令牌用户的所有角色,以及如果你正在使用的Web API不是(JWT令牌),那么这些令牌签署的默认数据保护DPAPI和加密,因此没有人可以与数据篡改令牌里面,除非他有发出此令牌的Web服务器mashineKey,所以不用担心数据保护。

As you stated you are using bearer tokens to protect your end points. I believe that there is little misunderstanding with what those bearer tokens magical string contains inside it. Well those tokens contains all the roles for the user you issued the token for, as well if you are using the default data protection DPAPI in Web API not (JWT Tokens) then those tokens are signed and encrypted so no one can tamper with the data inside the token unless he has the mashineKey for the web server issued this token, so do not worry about data protection.

我的建议是阅读从数据库用户的角色/索赔,也没有必要为这个解决方法和黑客你正在尝试做的,所有你需要做的是,当他们登录到设置为用户索赔在方法 GrantResourceOwnerCredentials 您可以通过获取用户随后从读取数据库中的作用和将它们设置为类型的要求设置它像这样的角色

My recommendation is to read the roles/claims for the user from the database, there is no need for this workarounds and hacks you are trying to do, all you need to do is to set the claims for the users when they login in method GrantResourceOwnerCredentials You can set it like this way by getting the user then reading the roles from DB and setting them as claim of type "Role"

 var identity = new ClaimsIdentity(context.Options.AuthenticationType);
 identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
 identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
 identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));

记住,当用户登录,那么您将收到一个承载签署并ecrypted令牌,它包含所有该用户的索赔,无需任何DB访问验证这只是发生一次。

Remember this only happens once when the user login, then you will receive a bearer signed and ecrypted token which contains all the claims for this user, no need to any DB access to verify it.

或者,如果你想创建数据库的身份,你可以使用下面的:

Or if you want to create the identity from Database you can use the below:

 public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
        // Add custom user claims here
        return userIdentity;
    }

然后在 GrantResourceOwnerCredentials 做如下:

ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType);

现在,一旦你与授权属性发送承载令牌的受保护的终点,如 [授权(角色=老师)] 我可以向你保证,你的code不会去到DB做任何查询的打开SQL事件探查器和检查的它会读取加密的令牌中的声明与一起角色要求,并检查该用户所属的教师的角色,允许或拒绝该请求。

Now once you send the bearer token to an protected end point with Authorize attribute such as [Authorize(Roles = "Teacher")] I can assure you that your code will not go to the DB to do any query open SQL profiler and check it will read the claims from the encrypted token along with the Roles claim and check if this user belongs to Teacher role and allow or deny the request.

我的博客上讲述<一个详细的5系列帖子href=\"http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/\">Token与<一个基于沿认证 href=\"http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/\">Authorization服务器和<一个href=\"http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/\">JWT令牌的。我建议你​​阅读这些职位,以获得更好的理解承载的令牌。

I've blogged a detailed series of 5 posts about Token Based Authentication along with Authorization server, and JWT tokens. I recommend you to read those posts to get better understanding of bearer tokens.

这篇关于我怎样才能没有查找到AspNetUserRoles表的WebAPI方法内用户的角色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆