【问题标题】:JWT authorization with roles in Identity Core使用 Identity Core 中的角色进行 JWT 授权
【发布时间】:2019-09-17 22:18:58
【问题描述】:

我无法理解Identity Core 中的Roles

我的AccountController 看起来像这样,我在GenerateJWTToken 方法的声明中添加了Roles

[HttpPost("Login")]
    public async Task<object> Login([FromBody] LoginBindingModel model)
    {
        var result = await this.signInManager.PasswordSignInAsync(model.UserName, model.Password, false, false);

        if (result.Succeeded)
        {
            var appUser = this.userManager.Users.SingleOrDefault(r => r.UserName == model.UserName);
            return await GenerateJwtToken(model.UserName, appUser);
        }

        throw new ApplicationException("INVALID_LOGIN_ATTEMPT");
    }

    [HttpPost("Register")]
    public async Task<object> Register([FromBody] RegistrationBindingModel model)
    {
        var user = new ApplicationUser
        {
            UserName = model.UserName,
            Email = model.Email,
            FirstName = model.FirstName,
            LastName = model.LastName
        };
        var result = await this.userManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
            await this.signInManager.SignInAsync(user, false);
            return await this.GenerateJwtToken(model.UserName, user);
        }

        throw new ApplicationException("UNKNOWN_ERROR");
    }

    private async Task<object> GenerateJwtToken(string userName, IdentityUser user)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, userName),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(ClaimTypes.NameIdentifier, user.Id),
            new Claim(ClaimTypes.Role, Role.Viewer.ToString()),
            new Claim(ClaimTypes.Role, Role.Developer.ToString()),
            new Claim(ClaimTypes.Role, Role.Manager.ToString())
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.configuration["JwtKey"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var expires = DateTime.Now.AddDays(Convert.ToDouble(this.configuration["JwtExpireDays"]));

        var token = new JwtSecurityToken(
            this.configuration["JwtIssuer"],
            this.configuration["JwtIssuer"],
            claims,
            expires: expires,
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

从这段代码中,我的令牌与 [Authorize] 控制器的属性完美配合。

我的问题是,在哪一步将role 添加到我注册的user 以使用(例如)[Authorize("Admin")]?如何将role 保存到数据库?

[Route("api/[controller]")]
[Authorize] //in this form it works ok, but how to add roles to it with JWT Token?
            //how to register user to role and get this role to JWT Token?
[ApiController]
public class DefaultController : ControllerBase

我的ApplicationUser

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Roles 的枚举:

public enum Role
{
    Viewer,
    Developer,
    Manager
}

如何将有关用户角色的信息保存到身份数据库,并在登录时让该角色正常工作[Authorize] 属性?

编辑:

我想要做的是将Roles 存储在我的用户枚举中。我想将用户注册为DeveloperManager 等。我相信我可以通过ApplicationUser 来做到这一点并添加Role 属性,但是我无法通过属性[Authorization(role)] 获得授权

【问题讨论】:

  • @WiktorZychla 感谢您的反馈,但我的项目是 core 2.1
  • 查看我的answer
  • @MuhammadHannan 感谢您的建议,但我认为并非如此。我对我的问题进行了编辑
  • @michasaucer 我也有同样的问题!!你找到解决这个问题的方法了吗?任何提示或文档链接都会有所帮助。

标签: c# asp.net-core asp.net-identity claims-based-identity


【解决方案1】:

在您的情况下,您不需要使用 IdentityUser 和身份数据库,您正在使用 JWT。使用定义的Roles 属性创建您的User 模型并将其简单地保存在数据库中。喜欢:

public class User
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public Role Role { get; set; }
}

public enum Role
{
   Viewer,
   Developer,
   Manager
}

令牌:

var user = // ...
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(your_seccret_key);
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(new Claim[] 
         {
             new Claim(ClaimTypes.Name, user.FirstName),
             new Claim(ClaimTypes.Name, user.LastName),
             new Claim(ClaimTypes.Role, user.Role)
         }),
     Expires = DateTime.UtcNow.AddDays(1),
     SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256Signature)
 };
 var token = tokenHandler.CreateToken(tokenDescriptor);
 user.Token = tokenHandler.WriteToken(token);

控制器方法:

[Authorize(Roles = Role.Developer)]
[HttpGet("GetSomethingForAuthorizedOnly")]
public async Task<object> GetSomething()
{ 
   // .... todo
}

【讨论】:

  • 也许,但我想使用 Identity 将用户存储在角色中。我找不到在身份中授权用户的任何解决方案。如果我想使用令牌,我需要使用 JWT
  • 这并没有什么大的好处。创建简单的用户模型,同时添加密码,读取密码+添加盐,而不是加密,找到安全算法,不要使用 md5 或 sha1。永远不要解密密码,加上尝试限制,你是安全的。
  • 假设我不使用Identity,那么如何检查角色?例如 - 这个链接说 .AddRoles -docs.microsoft.com/en-us/aspnet/core/security/authorization/… - 但既然我不使用身份,那么我还需要这条线吗?
【解决方案2】:

您可以将内置角色管理与 ASP.NET Identity 结合使用。由于您使用的是 ASP.NET Core 2.1,您可以先参考以下链接以启用身份系统中的角色:

https://stackoverflow.com/a/54069826/5751404

启用角色后,您可以注册角色/用户,然后为用户添加角色,例如:

private async Task CreateUserRoles()
{   
    IdentityResult roleResult;
    //Adding Admin Role
    var roleCheck = await _roleManager.RoleExistsAsync("Admin");
    if (!roleCheck)
    {

        IdentityRole adminRole = new IdentityRole("Admin");
        //create the roles and seed them to the database
        roleResult = await _roleManager.CreateAsync(adminRole);

        _roleManager.AddClaimAsync(adminRole, new Claim(ClaimTypes.AuthorizationDecision, "edit.post")).Wait();
        _roleManager.AddClaimAsync(adminRole, new Claim(ClaimTypes.AuthorizationDecision, "delete.post")).Wait();

        ApplicationUser user = new ApplicationUser {
            UserName = "YourEmail", Email = "YourEmail",

        };
        _userManager.CreateAsync(user, "YourPassword").Wait();

        await _userManager.AddToRoleAsync(user, "Admin");
    }

}

这样当该用户登录到您的应用程序时,您可以在 ClaimsPrincipal 中找到 role 声明,并且可以与 Authorizeattribute 和角色一起使用。

【讨论】:

  • 在 asp mvc 中是的,但是如果我想使用 webapi 怎么办?
  • 在web api中,直接使用JWT token,或者使用role claim手动登录:stackoverflow.com/a/55645212/5751404
  • 我还没有完全理解你的要求,JWT令牌传递给你的web api,你的web api端需要在ASP.NET身份系统中注册用户和角色吗?
  • 我忘了提,我的错。我的项目是webapi,我需要有令牌才能登录webapi 服务。这就是为什么我需要像JWT 这样的东西来从前端外部登录用户(webapi proj 是我的后端)
  • @michasaucer,那为什么不使用 JWT 并使用基于策略的授权呢?或者您可以手动解码令牌并使用角色声明登录:stackoverflow.com/questions/55628357/…
猜你喜欢
  • 2019-07-01
  • 2018-12-05
  • 2016-07-20
  • 2020-03-02
  • 2021-05-23
  • 1970-01-01
  • 2021-02-27
  • 2018-04-17
  • 2017-12-14
相关资源
最近更新 更多