扩展基于角色的授权时面临的问题

Posted

技术标签:

【中文标题】扩展基于角色的授权时面临的问题【英文标题】:issues faced while extend Role based authorization 【发布时间】:2020-07-04 22:43:25 【问题描述】:

当我尝试使用 Microsoft 身份扩展基于角色的授权时遇到了问题。

当调用登录操作方法时,如果没有将角色添加到声明列表中,它将生成令牌。

 var claims = new List<Claim>
        
            new Claim(ClaimTypes.Name,user.UserName),
            new Claim(ClaimTypes.NameIdentifier,user.Id.ToString())
        ;

        var roles = await _userManager.GetRolesAsync(user);  // If remove this await call then it work fine.

        foreach (var role in roles)
        
            claims.Add(new Claim(ClaimTypes.Role, role));
        

在生成令牌的同时将新角色添加到声明中后,我确实在几分钟后从服务器收到了任何响应,它会显示如下错误。

错误是:调用的目标已抛出异常。

在 ConfigureServices 方法下的 Startup.cs 类中。

    services.AddDbContext<DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            IdentityBuilder builder = services.AddIdentityCore<User>(opt =>
            
                opt.Password.RequireDigit = false;
                opt.Password.RequiredLength = 4;
                opt.Password.RequireNonAlphanumeric = false;
                opt.Password.RequireUppercase = false;
            );

            builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services);
            builder.AddEntityFrameworkStores<DataContext>();
            builder.AddRoleValidator<RoleValidator<Role>>();
            builder.AddRoleManager<RoleManager<Role>>();
            builder.AddSignInManager<SignInManager<User>>();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(auth =>
            
                auth.TokenValidationParameters = new TokenValidationParameters()
                
                    // ValidateIssuer = true,
                    // ValidIssuer = Configuration["AuthSettings:Issuer"],
                    // ValidateAudience = true,
                    // ValidAudience = Configuration["AuthSettings:Audience"],
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["AuthSettings:Key"])),
                    ValidateIssuer = false,
                    ValidateAudience = false
                ;
            );

   services.AddControllers(opt =>
            
                var policy = new AuthorizationPolicyBuilder()
           .RequireAuthenticatedUser()
           .Build();
                opt.Filters.Add(new AuthorizeFilter(policy));
            )
             .AddNewtonsoftJson(options =>
              options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

在 AuthController 中

 [HttpPost("login")]
    public async Task<IActionResult> Login(UserForLoginDto loginDto)
    

        var user = await _userManager.FindByNameAsync(loginDto.Username);
        var result = await _signInManager.CheckPasswordSignInAsync(user, loginDto.Password, false);
        if (result.Succeeded)
        
            var appUsers = await _userManager.Users.Include(e => e.Photos)
            .FirstOrDefaultAsync(next => next.NormalizedUserName == loginDto.Username.ToUpper());

            var userToReturn = _mapper.Map<UserForListDto>(appUsers);
            return Ok(new
            
                token = GeneratejwtToken(appUsers),
                user = userToReturn

            );
        
        else
        
            return Unauthorized();
        



    

    private async Task<string> GeneratejwtToken(User user)
    
        var claims = new List<Claim>
        
            new Claim(ClaimTypes.Name,user.UserName),
            new Claim(ClaimTypes.NameIdentifier,user.Id.ToString())
        ;

        var roles = await _userManager.GetRolesAsync(user);

        foreach (var role in roles)
        
            claims.Add(new Claim(ClaimTypes.Role, role));
        

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["AuthSettings:Key"]));
        var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
        var tokenDescriptor = new SecurityTokenDescriptor
        
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.Now.AddDays(1),
            SigningCredentials = signingCredentials

        ;
        var TokenHandler = new JwtSecurityTokenHandler();
        var token = TokenHandler.CreateToken(tokenDescriptor);
        return TokenHandler.WriteToken(token);
    

【问题讨论】:

【参考方案1】:

我解决了这个问题, 在调用 GeneratejwtToken 方法时,我忘记了使用 await 关键字,因为该方法是异步方法。

token = await GeneratejwtToken(appUsers)

【讨论】:

以上是关于扩展基于角色的授权时面临的问题的主要内容,如果未能解决你的问题,请参考以下文章

Angular Js 安全问题基于角色的授权

当基于角色的授权失败时,asp.net core 2.0 应用程序崩溃

多级基于角色授权的数据库设计

Spring Boot中基于​​角色的授权

Angularfire2 基于角色的授权,支持页面刷新

.NET Core 3.1 基于角色的 JWT 授权返回 403 禁止