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信息

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM