首页 > 解决方案 > 在客户端向 Principal 添加自定义声明(用于授权)

问题描述

我已经能够在 .net core 3.1 上成功实现我自己的 IdentityServer4 身份验证服务器,并且我有一个客户端 Web 应用程序连接到它。客户端成功接收访问令牌和 ID。令牌包含所有用户识别信息。

我的下一个目标是在我获得令牌之后,在呈现任何其他页面之前,将用户在客户端中拥有的权限作为声明添加到 HttpContext.User。权限存储在通过 subjectId 与用户关联的数据库中。

我需要有关在哪里可以添加这些声明的帮助,以便我的授权策略可以与主体中的声明一起使用。我希望每次发行令牌时都执行该过程。

PS我正在使用GetClaimsFromUserInfoEndpoint = true和SaveTokens = true的身份服务器的代码流。

谢谢!

标签: .net-coreidentityserver4asp.net-core-3.1

解决方案


您可以在 identityServer4 中使用 Profile sevise:

 services .AddIdentityServer(x =>
            {
                x.IssuerUri = "null";
                x.Authentication.CookieLifetime = TimeSpan.FromDays(10);
            })
.
.
.          
              .AddProfileService<ProfileService>();

这是一个很好的参考:http ://docs.identityserver.io/en/latest/reference/profileservice.html 而 ProfileService 可以是这样的代码模板:

public class ProfileService : IProfileService
{
    private readonly UserManager<ApplicationUser> _userManager;


    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;

    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));

        var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;

        var user = await _userManager.FindByIdAsync(subjectId);
        if (user == null)
            throw new ArgumentException("Invalid subject identifier");

        var claims = GetClaimsFromUser(user,subject);
        context.IssuedClaims = claims.Result.ToList();
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject));

        var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
        var user = await _userManager.FindByIdAsync(subjectId);

        context.IsActive = false;

        if (user != null)
        {
            if (_userManager.SupportsUserSecurityStamp)
            {
                var security_stamp = subject.Claims.Where(c => c.Type == "security_stamp").Select(c => c.Value).SingleOrDefault();
                if (security_stamp != null)
                {
                    var db_security_stamp = await _userManager.GetSecurityStampAsync(user);
                    if (db_security_stamp != security_stamp)
                        return;
                }
            }

            context.IsActive =
                !user.LockoutEnabled ||
                !user.LockoutEnd.HasValue ||
                user.LockoutEnd <= DateTime.Now;
        }
    }

    private async Task<IEnumerable<Claim>> GetClaimsFromUser(ApplicationUser user,ClaimsPrincipal subject)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtClaimTypes.Subject, user.Id),
            new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
            new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)

        };

        if (!string.IsNullOrWhiteSpace(user.Name))
            claims.Add(new Claim("name", user.Name));

        if (!string.IsNullOrWhiteSpace(user.LastName))
            claims.Add(new Claim("last_name", user.LastName));


        return claims;
    }
}

推荐阅读