zoukankan      html  css  js  c++  java
  • IdentityServer4授权和认证集成Identity和profile

    identiyt的使用可以看之前的文章:https://www.cnblogs.com/nsky/p/10323415.html

    之前的ids4授权服务器都是用的in-men方式把数据添加到内存,

    现在应该改成identity对接数据库操作,因为之前的代码有,就不一一创建了

    nuget包:IdentityServer4.AspNetIdentity

    那么之前的TestUser以及TestUserStore都要替换掉

    AddAspNetIdentity<ApplicationUser>()

    那么Profile是什么? Profile就是用户资料,ids 4里面定义了一个IProfileService的接口用来获取用户的一些信息,

    主要是为当前的认证上下文绑定claims。我们可以实现IProfileService从外部创建claim扩展到ids4里面。

    定义一个ProfileServices类继承IProfileService

    using AuthorizationServer.Models;
    using IdentityModel;
    using IdentityServer4.Models;
    using IdentityServer4.Services;
    using Microsoft.AspNetCore.Identity;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    namespace AuthorizationServer.Services
    {
        /// <summary>
        ///  Profile就是用户资料,ids 4里面定义了一个IProfileService的接口用来获取用户的一些信息
        ///  ,主要是为当前的认证上下文绑定claims。我们可以实现IProfileService从外部创建claim扩展到ids4里面。
        ///  然后返回
        /// </summary>
        public class ProfileServices : IProfileService
        {
            private readonly UserManager<ApplicationUser> _userManager;
            private readonly RoleManager<ApplicationRole> _roleManager;
            public ProfileServices(
                UserManager<ApplicationUser> userManager,
                RoleManager<ApplicationRole> roleManager)
            {
                _userManager = userManager;
                _roleManager = roleManager;
            }
    
            public async Task<List<Claim>> GetClaimsFromUserAsync(ApplicationUser user)
            {
                var claims = new List<Claim> {
                    new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
                    new Claim(JwtClaimTypes.PreferredUserName,user.UserName)
                };
    
                var role = await _userManager.GetRolesAsync(user);
                role.ToList().ForEach(f =>
                {
                    claims.Add(new Claim(JwtClaimTypes.Role, f));
                });
    
                if(!string.IsNullOrEmpty(user.Avatar))
                {
                    claims.Add(new Claim("avatar", user.Avatar));
                }
                claims.Add(new Claim("姓名", "tom"));
                return claims;
            }
    
            /// <summary>
            /// 获取用户Claims
            /// 用户请求userinfo endpoint时会触发该方法
            /// http://localhost:5003/connect/userinfo
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public async Task GetProfileDataAsync(ProfileDataRequestContext context)
            {
                var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
                var user = await _userManager.FindByIdAsync(subjectId);
                context.IssuedClaims =await GetClaimsFromUserAsync(user);
            }
    
            /// <summary>
            /// 判断用户是否可用
            /// Identity Server会确定用户是否有效
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public async Task IsActiveAsync(IsActiveContext context)
            {
                var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
                var user = await _userManager.FindByIdAsync(subjectId);
                context.IsActive = user != null; //该用户是否已经激活,可用,否则不能接受token
    
                /*
                 这样还应该判断用户是否已经锁定,那么应该IsActive=false
                 */
            }
        }
    }

    ConfigureServices也要修改:

    这样的话。配置基本上就完成了

    接下来用Hybrid Flow实现试试

    因为CodeIdToken 有2种方式返回profile

    ResponseType改成 code id_token

     options.ResponseType = OpenIdConnectResponseType.CodeIdToken;

    //设置从UserInfoEndpoint获取claims信息

    options.GetClaimsFromUserInfoEndpoint = true;

    获取后映射到claims

     options.GetClaimsFromUserInfoEndpoint = true;
    options.ClaimActions.MapJsonKey("sub", "sub");
     options.ClaimActions.MapJsonKey("preferred_username", "preferred_username");
      options.ClaimActions.MapJsonKey("avatar", "avatar");
     options.ClaimActions.MapCustomJson("role", job => job["role"].ToString());

    这样会返回的access_token信息也包含了该信息,

    但如果claims过大,那么access_token也会很大

    授权成功了。在view页面

    引入:@using Microsoft.AspNetCore.Authentication

    并获取

    这样就会有ProfileServices.cs类中获取的clsims了

    access_token中同样会有


    id_token中是不会有的

    上面说了,profile的cliams信息是通过access_token访问UserInfoEndpoint获取的

    我们也可以通过postman试试

    而这些信息都是从数据库读取出来的

     如果不设置GetClaimsFromUserInfoEndpoint=true

    它默认是false

    那么我们想得到怎么办,

    1:可以自己用access_token去获取一次

    2:授权服务器client设置 AlwaysIncludeUserClaimsInIdToken=true

    这样就会把返回的profile信息包含在idtoken中,好像idtoken也会有很大的可能

    好了。试试效果,这样其实idtoken和access_token都返回了profile信息

  • 相关阅读:
    线程练习-网络买票
    永久储存信息(已完善)
    Linux命令
    oracle(3)
    小结
    java开发中中文编码问题
    double保留两位小数
    oracle(2)
    javadate相关
    分布式
  • 原文地址:https://www.cnblogs.com/nsky/p/10352678.html
Copyright © 2011-2022 走看看