1. 程式人生 > >IdentityServer4授權和認證集成Identity和profile

IdentityServer4授權和認證集成Identity和profile

hybrid ros summary reading active led sync idc class

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

IdentityServer4授權和認證集成Identity和profile