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

Arn*_* F. 9 c# claims-based-identity asp.net-identity asp.net-core

我使用Windows身份验证的ASP.NET Core(基于.NET Framework).重点是,我需要在该用户上添加角色声明,并且此角色存储在远程数据库中.

我已经阅读了很多关于OWIN/Cookie/UserManager/UserStore/Identity等的内容,以至于我迷失了.

问题:如何以最简单的方式为整个应用程序的当前用户登录(窗口)添加角色声明?

我需要的是轻松使用[Authorize(Role= "MyAddedRole")]bool res = User.IsInRole("MyAddedRole")

谢谢

Arn*_* F. 8

回答我自己,所以我做了什么:

创建我自己的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
}
Run Code Online (Sandbox Code Playgroud)

然后创建了我自己的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

非常,在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);
        });
    }
Run Code Online (Sandbox Code Playgroud)

现在我可以自由使用[Authorize(Roles = "MyRole")]或者User.IsInRole("MyRole")甚至User.HasClaim(/* */)!

  • 您能否进一步解释如何定义从数据库中检索到的角色并将其相应地分配给用户? (3认同)
  • 似乎对于 asp.net core 3.1, 0) IClaimsTransformer 现在是 IClaimsTransformation, 1) AddEntityFrameworkStores 需要一个继承自 IdentityDbContext&lt;IdentityUser&gt; 的 db conetxt, 2) app.UseIdentity() 已经下降而有利于 app.UseAuthentication(); 3)在 IApplicationBuilder 中找不到 app.UseClaimsTransformation,我发现自己正在尝试为 asp.net core 3.1 找到解决方案,我希望这对其他人有帮助! (2认同)

小智 5

在答案旁边,我刚刚找到了答案,该答案在asp .net核心中是完全预定义的。当您添加声明时,只需:

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)
};
Run Code Online (Sandbox Code Playgroud)

之后,您可以按照以下说明使用它:

[Authorize(Roles = "Watever")]
Run Code Online (Sandbox Code Playgroud)

要么

User.IsInRole("Watever")
Run Code Online (Sandbox Code Playgroud)

  • 好的,所以您创建了一个新的声明列表。你不需要调用一些东西来为当前用户持久化它们吗? (2认同)

Mla*_* B. 5

您正在讨论的User对象有多个Identities,它们都可以有多个Claims

将自定义声明添加到 User 对象的一种方法是编辑由您选择的身份验证/授权框架(例如 OAuth)自动创建的身份,显然,该步骤特定于每个框架。归根结底是阅读该框架的文档,以找出正在创建身份的点,并使用添加新声明的自定义代码扩展该点。

另一种可能更简单的方法是创建一个新的 Identity 对象(其中包含所有附加声明)并使用AddIdentity() 方法将其添加到用户身份列表中。

当您访问User.Claims该枚举时,将返回您在 User 对象上拥有的所有身份的所有声明。

因此,无论您在应用程序代码中的哪个位置(我认为最合适的点是某种中间件),您都可以执行以下操作:

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);
Run Code Online (Sandbox Code Playgroud)

从那时起,每次调用都User.Claims将返回 User 对象上的所有原始声明以及您的附加声明。