简体   繁体   English

索赔比角色更好吗

[英]Is Claims Better Way to go rather than Roles

I am building a website(front end reactjs, backend asp.net web api core 2) and trying to figure how to do authentication/authorization.我正在构建一个网站(前端 reactjs,后端 asp.net web api core 2)并试图弄清楚如何进行身份验证/授权。

For authentication I pretty much will JWTBearer tokens, if the username and password match what I got for the user in my db, give them a token.对于身份验证,我几乎会使用 JWTBearer 令牌,如果用户名和密码与我在数据库中为用户获得的内容相匹配,则给他们一个令牌。

It is for authorization that I am not sure about, The last time I had to do something it was more have roles in your database and then check if that user had that role or not when they tried to access something.这是我不确定的授权,上次我必须做某事时,它更多地在您的数据库中具有角色,然后在该用户尝试访问某些内容时检查该用户是否具有该角色。

Now I was looking at this blog and the author talks about现在我正在看这个博客,作者谈到

Rather than try and store all the “roles” that a user might have (eg administrator, user, super user) you can store information about the user as claims.与其尝试存储用户可能拥有的所有“角色”(例如管理员、用户、超级用户),不如将有关用户的信息存储为声明。

I am confused about this, how does this work.我对此感到困惑,这是如何工作的。 Say I need one user to be able to see the very secret area of my site(ie admin area) but another user who is also logged in can't see it as he is a general user.假设我需要一个用户能够看到我网站的非常秘密的区域(即管理区域),但另一个同样登录的用户无法看到它,因为他是一个普通用户。

What information is used to make this claim?使用什么信息来提出此声明? What is being stored in the database?数据库中存储了什么?

With roles, you could have something like User can have a Roles (ie Admin) and then just check that when they try to do something.对于角色,您可以拥有像用户可以拥有角色(即管理员)之类的东西,然后在他们尝试做某事时进行检查。

I am also wondering how would the front end know what to hide(ie the link that says "admin area") as can you send back a result saying that they have a claim that allows them to see the admin area?我还想知道前端如何知道要隐藏什么(即显示“管理区域”的链接),因为您可以发回一个结果,说明他们有一个允许他们查看管理区域的声明吗?

Claims can be used to manage a wider array of use cases than Role, particularly when paired with Policies and Requirements .声明可用于管理比 Role 更广泛的用例,尤其是与Policies 和 Requirements配对时。 Two examples that come to mind:想到的两个例子:

  1. Requiring a user have a specific reputation in order to edit a record要求用户具有特定声誉才能编辑记录
  2. Requiring a user to be at least 21 to order a particular product要求用户年满 21 岁才能订购特定产品

One could create an "Over21" role, and a "Over1000Reputation" role, but maintaining role membership becomes unwieldy;可以创建一个“Over21”角色和一个“Over1000Reputation”角色,但是维护角色成员资格变得笨拙; you need to set up jobs to add (or remove) users from those roles as their age or reputation changes.您需要设置作业以随着年龄或声誉的变化从这些角色中添加(或删除)用户。

Instead, have your JWT include a Reputation and BirthDate claims:相反,让您的 JWT 包含 Reputation 和 BirthDate 声明:

identity.AddClaim(new Claim("Reputation", 722));
identity.AddClaim(new Claim("BirthDate", new DateTime(2000, 1, 1)));

Your code could then implement a Requirement and AuthorizationHandler that calculates whether the user should be authorized based on these claim values:然后,您的代码可以实现一个RequirementAuthorizationHandler ,根据这些声明值计算用户是否应该被授权:

public class ReputationRequirement : IAuthorizationRequirement
{
    public int Reputation { get; private set; }

    public ReputationRequirement (int reputation)
    {
        Reputation = reputation;
    }
}

Paired with an AuthorizationHandler along these lines:沿着这些线与AuthorizationHandler配对:

public class ReputationHandler : AuthorizationHandler<ReputationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ReputationRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == "Reputation"))
        {
            return Task.CompletedTask;
        }

        var reputation = context.User.FindFirst(c => c.Type == "Reputation").Value as int;
        if (reputation >= requirement.Reputation)  
            context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

In your startup's ConfigurationServices , you can give a name ( Policy ) to a particular instance of your requirement:在您的初创公司的ConfigurationServices ,您可以为您的需求的特定实例命名( Policy ):

services.AddAuthorization(options =>
{
    options.AddPolicy("Reputation750", policy => policy.Requirements.Add(new ReputationRequirement(750)));
    options.AddPolicy("OldAndWise", policy => 
    {
        policy.Requirements.Add(new ReputationRequirement(750));
        policy.Requirements.Add(new MinimumAgeRequirement(40));
    }
});

Lastly, you can mark MVC controllers or methods with a policy:最后,您可以使用策略标记 MVC 控制器或方法:

[Authorize(Policy = "OldAndWise")]
public class StackOverflowWineController : Controller
{
    // omitted for brevity
}

Note the example linked to has more detail that this brief code snippet.请注意链接到的示例比这个简短的代码片段有更多的细节。

Regarding storage of claims in a database, that depends on the use case.关于在数据库中存储声明,这取决于用例。 When treating Roles as Claims, you would still have something like a UserRoles and RoleMembership tables.将角色视为声明时,您仍然会有类似UserRolesRoleMembership表的内容。 For Reptuation and BirthDate , it would probably make more sense to store them in a User table, rather than some sort of dedicated generic Claims table.对于ReptuationBirthDate ,将它们存储在 User 表中可能更有意义,而不是某种专用的通用Claims表。

Roles can still be used like in the older versions.角色仍然可以像在旧版本中一样使用。 Claims are simply a way to store more user data and provide more flexibilities with the authentication.声明只是一种存储更多用户数据并为身份验证提供更多灵活性的方法。 You can add them to a list like this:您可以将它们添加到这样的列表中:

List<Claim> claims = new List<Claim> {
    new Claim(ClaimTypes.Name, "username"),
    new Claim(ClaimTypes.Role, "First Role"),
    new Claim(ClaimTypes.Role, "Second Role"),
    new Claim(ClaimTypes.Role, "Third Role")
};

You can authorize any controller or action using [Authorize(Roles = "user, superUser")] .您可以使用[Authorize(Roles = "user, superUser")]授权任何控制器或操作。 If you want to display something to a user based on roles, you can use @if (User.IsInRole("User")) .如果要根据角色向用户显示某些内容,可以使用@if (User.IsInRole("User"))

As of JWT creation, you can have a look at this class: https://github.com/neville-nazerane/netcore-jwt-sample/blob/master/website/TokenGenerator.cs JWT的创建,你可以看看这个类: https : //github.com/neville-nazerane/netcore-jwt-sample/blob/master/website/TokenGenerator.cs

It has utility functions to create a JWT with a given user name and also one that takes in a username and a comma separated string of roles.它具有实用功能,可以使用给定的用户名创建 JWT,还可以使用用户名和逗号分隔的角色字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM