我的要求很简单:
>我开发需要身份验证和授权的应用程序(xamarin表单)
>我需要一个系统来存储我的用户的身份(名称,密码,角色,电话……) – > ASP.net身份
>我需要一个系统来验证我的用户 – > IdentityServer 4
>每个用户的角色非常有限(用户/管理员),不会更改
>我需要一个API后端和一个MVC管理站点(asp.net核心)
>我想使用[Authorize(Roles =“Admin”)]限制对某些API / MVC控制器的访问
我花了无数个小时尝试不同的配置,以便在认证后将asp.net Identity角色传递给我的MVC应用程序,但没有运气.目的如第6点所述.
我也花了无数个小时阅读,但我感觉自版本v1.0.0以来,角色的实现IdentityServer4.AspIdentity已经发生了很大的变化.
在阅读了很多关于这一点后,仍然不清楚如何实际实现这一点,因为似乎仅在2个月前描述的一些解决方案不再有效.
所以,现在我相信有两条路:
>仅通过请求身份令牌将角色置于身份令牌中
并使用AlwaysIncludeInIdToken?
>让客户端检索角色
使用userinfo端点并以某种方式将它们注入到
httpcontext(?)允许mvc使用[Authorize(Roles =.)进行检查
“管理”)?
无论如何,这是我的假设.
那么,请详细帮助解释/记录,以便我们能够以持久的方式开始实施吗?一些可行的例子也很棒.
解决方法
>在Identity Server端包含角色/其他声明
>在客户端包含角色/其他声明
包含在Identity Server端
ravi punjwani在“如何使用带有IdentityServer4的ASP.Net标识添加要包含在access_token中的其他声明”中提供了答案.他的解决方案仍在草案中,但解决方案允许您在令牌发送回客户端之前添加任何声明.这是链接:How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4
包括在客户端
这个问题有点困难,因为它涉及在客户端的请求管道中添加“IClaimsTransformer”.结果是,对于每个请求,Claimstransformer将检索用户的声明并将其添加到用户身份声明(令牌). Claimstransformer的设置并不容易,因为让DI工作很棘手,但经过大量研究后,celow解决方案为我做了这件事.
Custom ClaimsTransformer类在中间件中进行转换:
公共类KarekeClaimsTransformer:IClaimsTransformer
{
private readonly UserManager _userManager;
public KarekeClaimsTransformer(UserManager<ApplicationUser> userManager) { _userManager = userManager; } public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context) { if (context.Principal.Identity.IsAuthenticated) { Claim userId = context.Principal.FindFirst("sub"); if (context.Principal.FindFirst("role") == null && userId != null) { ApplicationUser user = await _userManager.FindByIdAsync(userId.Value); var roles = await _userManager.GetRolesAsync(user); foreach (var role in roles) { ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(JwtClaimTypes.Role,role,"http://schemas.microsoft.com/ws/2008/06/identity/claims/role")); } } } return Task.FromResult(context.Principal).Result; } }
在Client启动类中,您需要将其添加到ConfigureServices中的范围
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddDbContext<ApplicationDbContext>(options => options.UsesqlServer(Configuration.GetConnectionString("DefaultConnection"))); ... services.AddScoped<IClaimsTransformer,KarekeClaimsTransformer>(); // Add framework services. services.AddMvc(); }
最后,添加配置:
public void Configure(IApplicationBuilder app,IHostingEnvironment env,ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions { Authority = "http://localhost:5000",RequireHttpsMetadata = false,ApiName = "api1" }); app.UseClaimsTransformation((context) => { IClaimsTransformer transformer = context.Context.RequestServices.GetrequiredService<IClaimsTransformer>(); return transformer.TransformAsync(context); }); app.UseMvc(routes => { routes.MapRoute( name: "default",template: "api/{controller}/{action?}/{id?}"); }); }