asp.net-mvc - 如何将 ASP.net 身份角色放入 Identityserver4 身份 token 中

标签 asp.net-mvc asp.net-core identityserver4

虽然我很高兴 IdentityServer4 的存在并在很多方面使我在身份验证方面的生活变得更加轻松,但我偶然发现了这个问题以及社区内关于向声明添加角色的许多讨论。

我的要求很简单:

  1. 我开发需要身份验证和授权的应用(xamarin 表单)
  2. 我需要一个系统来存储用户的身份(姓名、密码、角色、电话……)-> ASP.net Identity
  3. 我需要一个系统来验证我的用户 -> IdentityServer 4
  4. 每个用户的角色非常有限(用户/管理员)并且不会改变
  5. 我需要一个 API 后端和一个 MVC 管理网站 (asp.net core)
  6. 我想使用 [Authorize(Roles = "Admin")] 限制对某些 API/MVC Controller 的访问

我花了无数个小时尝试不同的配置,以便在身份验证后将 ASP.NET 身份角色传递到我的 MVC 应用程序,但没有成功。目的如第 6 点所述。

我也花了无数个小时阅读,但我有一种感觉,自 v1.0.0 版本以来,有关角色的 IdentityServer4.AspIdentity 实现已经发生了很大变化。

在阅读了很多相关内容后,仍然不清楚如何实际实现这一点,因为两个月前描述的一些解决方案似乎不再有效。

所以,目前我相信有两条路:

  1. 仅通过请求身份 token 来扮演身份 token 的角色 并使用AlwaysInincludeInIdToken?
  2. 让客户端检索角色 使用 userinfo 端点并以某种方式将它们注入(inject) httpcontext(?) 允许 mvc 使用 [Authorize(Roles = “管理员”)]?

无论如何,这是我的假设。

那么,请帮忙详细解释/记录,以便我们可以开始以持久的方式实现这一点?一些可行的例子也很棒。

最佳答案

因此,经过调查,我想出了两种方法来做到这一点:

  1. 在身份服务器端包含角色/其他声明
  2. 包括客户端的角色/其他声明

包含在身份服务器端

ravi punjwani 在“如何使用 ASP.Net Identity 和 IdentityServer4 添加要包含在 access_token 中的附加声明”中提供了答案。他的解决方案仍处于草稿阶段,但该解决方案允许您在将 token 发送回客户端之前添加任何声明。这是链接:How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4

包含在客户端

这个有点困难,因为它涉及在客户端的请求管道中添加“IClaimsTransformer”。结果是,每个请求,Claimstransformer 将检索用户的声明并将其添加到用户身份声明( token )中。 Claimstransformer 的设置并不容易,因为让 DI 工作很棘手,但经过大量研究,celow 解决方案为我做到了。

自定义 ClaimsTransformer 类在中间件中进行转换: 公共(public)类 KarekeClaimsTransformer :IClaimsTransformer { 私有(private)只读 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();
    }

最后在Configure中添加:

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

关于asp.net-mvc - 如何将 ASP.net 身份角色放入 Identityserver4 身份 token 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41682434/

相关文章:

azure - 在 Controller 中获取 Azure AppSettings

c# - 失败 : Microsoft. AspNetCore.Antiforgery.Internal.DefaultAntiforgery

asp.net-identity - 转换和规范化来自外部身份验证提供商的声明的最佳方法

asp.net-mvc - 如何在脚本部分调用部分 View

c# - 如何在 ASP.NET MVC 中定义这个路由?

c# - Asp .net MVC 5路由属性与路由之间的ID

azure-active-directory - IdentityServer4 和 Azure AD - 输入凭据后将空白页 404 设置为 login.live

c# - 为什么保存记录时Guid会改变?

c# - 如何在 .NET Core 2.1 中重现复杂参数的 [FromUri] 行为

asp.net-core - 我可以验证使用带有 .net 后端的 native iOS sdk 创建的 Facebook jwt token 吗?