Identity Server通过ProfileService返回用户角色

Identity Server通过ProfileService返回用户角色

Identity Server系列目录

  1. Blazor Server访问Identity Server 4单点登录 - SunnyTrudeau - 博客园 (cnblogs.com)
  2. Blazor Server访问Identity Server 4单点登录2-集成Asp.Net角色 - SunnyTrudeau - 博客园 (cnblogs.com)
  3. Blazor Server访问Identity Server 4-手机验证码登录 - SunnyTrudeau - 博客园 (cnblogs.com)
  4. Blazor MAUI客户端访问Identity Server登录 - SunnyTrudeau - 博客园 (cnblogs.com)
  5. Identity Server 4项目集成Blazor组件 - SunnyTrudeau - 博客园 (cnblogs.com)
  6. Identity Server 4退出登录自动跳转返回 - SunnyTrudeau - 博客园 (cnblogs.com)

 

 

之前采用自定义IdentityResource的方式实现了从Identity Server返回用户角色,

public static class Config

    {

        public static IEnumerable<IdentityResource> IdentityResources =>

            new IdentityResource[]

            {

                new IdentityResources.OpenId(),

                new IdentityResources.Profile(),

                new IdentityResource("role", new string[]{JwtClaimTypes.Role })

            };

 

最近才发现可以通过ProfileService返回用户角色,微软官网上有相关介绍:

使用 Identity 服务器保护托管 ASP.NET Core Blazor WebAssembly 应用 | Microsoft Docs

 

决定改用ProfileService方案。

 

修改Identity Server服务端

修改AspNetId4Web认证服务器,可以照搬官网ProfileService的代码。

using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Services;
using System.Threading.Tasks;
namespace AspNetId4Web
{

    public class ProfileService : IProfileService
    {
        public ProfileService()
        {
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var nameClaim = context.Subject.FindAll(JwtClaimTypes.Name);
            context.IssuedClaims.AddRange(nameClaim);

            var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);
            context.IssuedClaims.AddRange(roleClaims);

            await Task.CompletedTask;
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            await Task.CompletedTask;
        }
    }
}

 

 

Startup.cs 中注册配置文件服务:

builder.Services.AddTransient<IProfileService, ProfileService>();

 

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

 

config配置客户端不需要添加role了。

new Client()
                {
                    ClientId="BlazorServerOidc",
                    ClientName = "BlazorServerOidc",
                    ClientSecrets=new []{new Secret("BlazorServerOidc.Secret".Sha256())},

                    AllowedGrantTypes = GrantTypes.Code,

                    AllowedCorsOrigins = { "https://localhost:5501" },
                    RedirectUris = { "https://localhost:5501/signin-oidc" },
                    PostLogoutRedirectUris = { "https://localhost:5501/signout-callback-oidc" },

                    //效果等同客户端项目配置options.GetClaimsFromUserInfoEndpoint = true
                    //AlwaysIncludeUserClaimsInIdToken = true,

                    //AllowedScopes = { "openid", "profile", "scope1", "role", }
                    //通过ProfileService返回用户角色
                    AllowedScopes = { "openid", "profile", "scope1", }
                },

 

 

修改Blazor Server客户端

修改BlzOidc项目,配置oidc参数,也不再需要role了。

//指定要取哪些资料(除Profile之外,Profile是默认包含的)

                options.Scope.Add("scope1");

                //通过ProfileService返回用户角色

                //options.Scope.Add("role");

 

然后在VS2022同时启动两个项目,测试可以看到BlzOidc项目登录之后可以获取到用户角色。

 

尝试通过ProfileService返回更多用户声明

var emailClaims = context.Subject.FindAll(JwtClaimTypes.Email);

            context.IssuedClaims.AddRange(emailClaims);

 

            var phoneNumberClaims = context.Subject.FindAll(JwtClaimTypes.PhoneNumber);

            context.IssuedClaims.AddRange(phoneNumberClaims);

 

但是有的可以,例如email,有的不行,例如phoneNumber,也是奇怪。

 

DEMO代码地址:https://gitee.com/woodsun/blzid4

 

posted on 2021-12-01 20:24  SunnyTrudeau  阅读(286)  评论(0编辑  收藏  举报