如何使用keycloak在.net core 5.0与asp.net core Identity? &



我在我的项目中使用asp.net core 5.0 webapi与CQRS,并且已经有jwt实现。没有使用aspnet核心中的角色管理,而是手动添加了aspnet用户表中的角色字段,并且到处都在使用。在互联网上,我找不到任何文章来实现现有的身份验证和授权。我的观点是现在用户登录他们的电子邮件+密码,这个想法并不适用于所有,但对于一些用户,他们已经存储在keycloak中,或者对于一些用户,我们将存储在那里,给我们的应用程序使用keycloak登录选项。

场景1:

我有admin@gmail.com在我的db和keycloak,两者都是他们在管理角色,我需要给两个登录我的应用程序,第一场景已经工作需要实现第二场景旁边的第一。

只找到这篇实现安全应用程序的文章(因为我们已经没有尝试替换而是扩展)

中等keycloak

jwt配置如下:

public static IServiceCollection AddCustomAuthentication(this IServiceCollection services,
IConfiguration configuration)
{
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.GetSection("AppSettings:Token").Value));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateAudience = false,
ValidateIssuer = false,
ClockSkew = TimeSpan.Zero
};
opt.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});

return services;
}

我的jwt服务看起来像:

public JwtGenerator(IConfiguration config)
{
_key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.GetSection("AppSettings:Token").Value));
}
public string CreateToken(User user)
{
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, user.Id),
new(ClaimTypes.Email, user.Email),
new(ClaimTypes.Name, user.UserName),
new(ClaimTypes.Role, user.Role.ToString("G").ToLower())
};

var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddMinutes(15),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}

我的登录方法如下:

public async Task<GetToken> Handle(LoginCommand request, CancellationToken cancellationToken)
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null)
throw new BadRequestException("User not found");

UserManagement.ForbiddenForLoginUser(user);
var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, false);
if (result.Succeeded)
{
user.IsRoleChanged = false;

RefreshToken refreshToken = new RefreshToken
{
Name = _jwtGenerator.GenerateRefreshToken(),
DeviceName = $"{user.UserName}---{_jwtGenerator.GenerateRefreshToken()}",
User = user,
Expiration = DateTime.UtcNow.AddHours(4)
};
await _context.RefreshTokens.AddAsync(refreshToken, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return new GetToken(_jwtGenerator.CreateToken(user),refreshToken.Name);
}
throw new BadRequestException("Bad credentials");
}

我的授权处理器:

public static IServiceCollection AddCustomMvc(this IServiceCollection services)
{
services.AddMvc(opt =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
// Build the intermediate service provider
opt.Filters.Add<CustomAuthorizationAttribute>();
}).AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<CreateProjectCommand>());
return services;
}

除了我目前的方法之外,实现keycloak认证+授权的最佳实践是什么,并让用户在两种情况下登录,正常登录和keycloak登录。

注:Ui是不同的,我们使用的是angular,这个只是webapi作为后端。

由于您的登录方法返回jwt,您可以通过链接.AddJwtBearer()来配置多个承载令牌,一个用于您的正常登录,一个用于keycloak。

这里有一个问题的链接,可以解决您的问题:使用多个jwt承载身份验证。

Keycloak配置:

  • 转到角色->Realm Roles并创建相应的角色
  • 转到客户端->你的客户->映射器。
  • 创建一个新的角色映射器并选择"用户领域角色";对于映射器类型,"角色"获取令牌声明名称和"字符串";用于声明JSON类型。如果没有映射,之前配置的角色将嵌套在jwt的其他地方。

您可以在jwt中使用调试器。IO检查您的令牌是否正确。结果应该如下所示:

{
"exp": 1627565901,
"iat": 1627564101,
"jti": "a99ccef1-afa9-4a62-965b-15e8d33de7de",
// [...]
// roles nested in realm_access :(
"realm_access": {
"roles": [
"offline_access",
"uma_authorization",
"Admin"
]
},
// [...]
// your mapped roles in your custom claim
"roles": [
"offline_access",
"uma_authorization",
"Admin"
]
// [...]
}

相关内容

  • 没有找到相关文章

最新更新