前言:
這是一篇實踐指南,不會過多的解釋原理(因為我也說不清楚,想了解的同學請移步老張的博客,里面有非常詳細的介紹),本篇文章講解如何簡單的使用IDS4來實現單點登錄,以及遇到的一些坑
實現功能:
1.持久化數據到數據庫
2.自定義認證
3.創建用戶
4.創建客戶端列表
5.創建資源列表
6.服務端部署
准備工作:
1.Linux服務器(建議Centos 7+)
2.Mysql(5.7+)
3..net core SDK 3.1
4.基於內存模型,能簡單使用IDS4
歡樂時光(吹牛逼),就要開始了........
開源地址:https://github.com/wmowm/gourd/
項目結構如圖所示,MVC項目,授權服務,資源服務
在持久化數據庫過程中,我遇到了很多問題,這里就不過多說明了,這也是第一道坎,我這里的遷移文件已經整理好了,准備一個空的mysql數據庫,取消InitializeDatabase(app)的注釋,運行項目即可
Identity有自己的一套驗證規則(太過於復雜,沒那么多精力去折騰),我也在這個上吃了大虧,將它替換成我們熟悉的模式就可以了,怎么簡單怎么來
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { try { var userName = context.UserName; var password = context.Password; //驗證用戶,這么可以到數據庫里面驗證用戶名和密碼是否正確 var claimList = await ValidateUserAsync(userName, password); // 驗證賬號 context.Result = new GrantValidationResult ( subject: userName, authenticationMethod: "custom", claims: claimList.ToArray() ); } catch (Exception ex) { //驗證異常結果 context.Result = new GrantValidationResult() { IsError = true, Error = ex.Message }; } }
/// <summary> /// 驗證用戶 /// </summary> /// <param name="loginName"></param> /// <param name="password"></param> /// <returns></returns> private async Task<List<Claim>> ValidateUserAsync(string loginName, string password) { //TODO 這里可以隨意驗證了 var user = await _context.Users.FirstAsync(m => m.UserName == loginName && m.PasswordHash == password); if (user == null) throw new Exception("登錄失敗,用戶名和密碼不正確"); return new List<Claim>() { new Claim(ClaimTypes.Name, $"{loginName}"), }; }
創建用戶,在初始化的時候,我們已經默認添加了一個用戶進去了,由於使用自定義的驗證規則,這里就可以隨便弄了,只要把數據插入到指定的表就可以了
#region 讀取初始化數據 string userId = Guid.NewGuid().ToString(); string roleId = Guid.NewGuid().ToString(); List<SysUser> usereInfo = new List<SysUser>() { new SysUser() { Id = userId, Account = "tibos", Name = "tibos", Password = "123456" //這里建議存MD5密文 } }; List<SysRole> SysRole = new List<SysRole>() { new SysRole() { Id = roleId, Memo = "管理員", Name = "admin" } }; List<SysUserRole> SysUserRole = new List<SysUserRole>() { new SysUserRole() { Id = Guid.NewGuid().ToString(), RoleId = roleId, UserId = userId } }; #endregion
我也用LayUI寫了一個簡單的CRUD,方便大家添加用戶
添加客戶端,這里面的水就有點深了,涉及到的表有點多,作為一個懶人,我肯定是不會每個表都去弄的,參考初始化導入內存模型里的客戶端,我弄了兩個最常用的客戶端,webapi,mvc 這個對應IDS4里的AllowedGrantTypes類型,我們常用的客戶端分為
1.傳統的Web項目,如mvc
2.前端項目, 如vue
3.桌面程序, 如winform,postman
這些我項目里都有實踐
它的添加是一個json文件,可以參考內存模型自己隨意改
添加資源比較簡單,每個資源擁有多個密鑰
它們三者的關系,因為我把用戶單獨提出來了,這里只說客戶端與資源, 一個客戶端的訪問范圍可以指定多個資源
做完了這些,你以為你已經掌握IDS4了,其實還差的遠,本地一切正常,部署到服務器上的時候,又是一堆問題
1.https問題,建議在程序里做強行跳轉,而不是在nginx里跳,nginx http重定向到https的時候,ids4檢查是不通過的,但是在iis上卻是正常的
2.跨域問題,建議也在程序里設置允許跨域,如果nginx跟程序都設置了允許跨域,則會出現兩個請求頭的異常
3.前端程序,第一次登錄成功,回調的地址沒有攜帶id_token,我這里是再回調頁面再重新登錄一次,第二次checksession會帶上id_token,這樣就可以拿令牌換access_token了,在使用access_token訪問受保護的資源
4.受保護資源最好也配置成https,當web站點是https時,js請求http的api資源會報錯,這個是瀏覽器限制
AllowedGrantTypes