简体   繁体   English

ASP.NET Core - 向用户添加角色声明

[英]ASP.NET Core - Add role claim to User

I've an ASP.NET Core (based on .NET Framework) using Windows Authentication.我有一个使用 Windows 身份验证的 ASP.NET Core(基于 .NET Framework)。 Point is, I need to add a role claim on that user and this role is stored in a distant database.重点是,我需要为该用户添加一个角色声明,并且该角色存储在远程数据库中。

I've read so much thing about OWIN/Cookie/UserManager/UserStore/Identity and so on that I'm lost.我读了很多关于 OWIN/Cookie/UserManager/UserStore/Identity 的东西,我迷路了。

Question : How do I add a role claim for current user logged in (windows) for the whole application in the easiest way?问题:如何以最简单的方式为整个应用程序的当前登录用户(Windows)添加角色声明?

What I need is to easily use [Authorize(Role= "MyAddedRole")] or bool res = User.IsInRole("MyAddedRole")我需要的是轻松使用[Authorize(Role= "MyAddedRole")]bool res = User.IsInRole("MyAddedRole")

Thanks谢谢

Answering myself, so what I did :回答自己,所以我做了什么:

Create my own UserClaimStore (I only need this store, not the others):创建我自己的 UserClaimStore(我只需要这个商店,不需要其他商店):

public class MyIdentityStore :
    IUserClaimStore<IdentityUser>
{
    private MyDbContext _myDbContext;
    private bool _disposed = false; 

    public MyIdentityStore(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

    #region IUserClaimStore
    public Task<IList<Claim>> GetClaimsAsync(IdentityUser user, CancellationToken cancellationToken)
    {
        // logic here to retrieve claims from my own database using _myDbContext
    }

    // All other methods from interface throwing System.NotSupportedException.
    #endregion

    #region IDisposable Support

    protected virtual void Dispose(bool disposing)
    { /* do cleanup */ }
    #endregion
}

Then created my own ClaimTransformer :然后创建了我自己的 ClaimTransformer :

public class MyClaimsTransformer : IClaimsTransformer
{
    private UserManager<IdentityUser> _userManager;

    public MyClaimsTransformer(UserManager<IdentityUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
    {
        var identity = ((ClaimsIdentity)context.Principal.Identity);

        // Accessing the UserClaimStore described above
        var claims = await _userManager.GetClaimsAsync(new IdentityUser(identity.Name));
        identity.AddClaims(claims);

        return await Task.FromResult(context.Principal);
    }
}

Endly, in Startup.cs :最后,在 Startup.cs 中:

    public void ConfigureServices(IServiceCollection services)
    {
        /* All other stuff here */ 

        // Adding Database connection
        services.AddDbContext<MyDbContext>(o => /* my options */);

        // Associates our database and store to identity
        services.AddIdentity<IdentityUser, IdentityRole>()
            .AddEntityFrameworkStores<MyDbContext>()
            .AddUserStore<MyIdentityStore>();

        // Claims transformation from database to claims
        services.AddTransient<IClaimsTransformer, MyClaimsTransformer>();
    }


    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        /* All other stuff here */ 

        app.UseIdentity();

        app.UseClaimsTransformation(async (context) =>
        { // Retrieve user claims from database
            IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
            return await transformer.TransformAsync(context);
        });
    }

And now I can freely use [Authorize(Roles = "MyRole")] or User.IsInRole("MyRole") or even User.HasClaim(/* */) !现在我可以自由使用[Authorize(Roles = "MyRole")]User.IsInRole("MyRole")甚至User.HasClaim(/* */)

Well beside the answers, I just found the answer which is totally predefined in asp .net core.除了答案之外,我刚刚找到了在 asp .net core 中完全预定义的答案。 When you are adding claims just :当您添加声明时:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, UserName),
    new Claim(ClaimTypes.Role, "User"),
    new Claim(ClaimTypes.Role, "Admin"),
    new Claim(ClaimTypes.Role, Watever)
};

after that you can just use it as said:之后,您可以按如下方式使用它:

[Authorize(Roles = "Watever")]

or

User.IsInRole("Watever")

A User object you're talking about has multiple Identities , which all can have multiple Claims .您正在谈论的User对象有多个Identities ,它们都可以有多个Claims

One way to add custom claims to the User object is to edit the Identity that is automatically created by your authentication/authorization framework of choice (eg OAuth) and that step is specific to each framework, obviously.向 User 对象添加自定义声明的一种方法是编辑由您选择的身份验证/授权框架(例如 OAuth)自动创建的身份,显然,该步骤特定于每个框架。 It boils down to read the docs for that framework to figure out at which point an Identity is being created and extened that point with your custom code adding new claims.归根结底是阅读该框架的文档以找出正在创建身份的时间点,并使用您的自定义代码添加新声明来扩展该时间点。

Another, maybe simpler, way is to create a new Identity object (which holds all your additional Claims) and add it to the User list of identities, using AddIdentity() method .另一种可能更简单的方法是使用AddIdentity() 方法创建一个新的 Identity 对象(其中包含所有附加声明)并将其添加到身份的用户列表中。

When you access User.Claims that enumeration will return all the claims from all the identities you have on the User object.当您访问User.Claims ,该枚举将返回您在 User 对象上拥有的所有身份的所有声明。

So, wherever you're in your application code (the most suitable point would be a sort of a middleware, I suppose) you can do something like this:因此,无论您在应用程序代码中的哪个位置(我认为最合适的点是某种中间件),您都可以执行以下操作:

var myIdentity = new ClaimsIdentity(new []
{
    new Claim("claim type", "claim value"), 
    new Claim("claim type", "claim value"), 
    new Claim("claim type", "claim value"), 
});

context.User.AddIdentity(myIdentity);

From that point on, each call to User.Claims will return all the original claims on the User object plus your additional claims.从那时起,对User.Claims每次调用User.Claims将返回对 User 对象的所有原始声明以及您的其他声明。

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

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