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

30
我有一个基于.NET Framework的ASP.NET Core应用程序,使用Windows身份验证。问题是,我需要在该用户上添加一个角色声明,而此角色存储在一个远程数据库中。
我读了很多关于OWIN/Cookie/UserManager/UserStore/Identity等的东西,以至于我迷失了方向。
问题:最简单的方法如何为当前已登录(Windows)用户在整个应用程序中添加角色声明?
我需要的是轻松地使用[Authorize(Role= "MyAddedRole")]bool res = User.IsInRole("MyAddedRole") 谢谢
3个回答

25

除了答案之外,我在 asp .net core 中找到了一个完全预定义的答案。当您添加声明时,只需执行以下操作:

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)
};

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

[Authorize(Roles = "Watever")]
User.IsInRole("Watever")

3
好的,你要创建一个新的索赔清单。你需要调用一些内容来将它们保存在当前用户的记录中吗? - Bob.at.Indigo.Health
你应该使用ClaimsIdentity将其添加到cookie中,只需在.net core中搜索此await HttpContext.SignInAsync()。 - ashk hp

18

回答自己,我所做的是:

创建了自己的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
}

然后我创建了自己的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);
    }
}

最后,在 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);
        });
    }

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


3
你能否更详细地解释一下,如何从你的数据库中检索角色定义并相应地分配给用户? - iAziz
1
似乎对于asp.net core 3.1,0)IClaimsTransformer现在是IClaimsTransformation,1)AddEntityFrameworkStores需要一个继承自IdentityDbContext<IdentityUser>的db conetxt,2)app.UseIdentity()已被舍弃并换成了app.UseAuthentication();而3)app.UseClaimsTransformation在IApplicationBuilder中未找到,所以我发现自己正在尝试为asp.net core 3.1找到解决方案。希望这能帮助其他人! - juagicre

4

你所谈论的用户对象具有多个身份标识, 这些身份标识都可以拥有多个声明

向用户对象添加自定义声明的一种方法是编辑由您选择的身份验证/授权框架(例如OAuth)自动创建的身份标识,这一步骤对于每个框架都是特定的。它归结为阅读该框架的文档,以确定在何时创建身份标识,并通过自定义代码扩展该点以添加新声明。

另一种可能更简单的方法是创建一个新的Identity对象(其中包含所有附加的Claims),并使用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);

从那时起,每次调用 User.Claims 都会返回 User 对象上的所有原始声明加上您额外添加的声明。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接