網站首頁 編程語言 正文
基礎信息
1.什么是鑒權授權?
- 鑒權是驗證用戶是否擁有訪問系統的權利,授權是判斷用戶是否有權限做一些其他操作。
2.傳統的Session 和Cookie
- 主要用于無狀態請求下的的用戶身份識別,只不過Session將信息存儲在服務端,Cookie將信息存儲在客戶端。
Session
在客戶端第一次進行訪問時,服務端會生成一個Session id返回到客戶端
客戶端將Session id存儲在本地后續每一次請求都帶上這個id
服務端從接收到的請求中根據Session id在自己存儲的信息中識別客戶端
Cookie
在客戶端訪問服務器時,服務端會在響應中頒發一個Cookie
客戶端會把cookie存儲,當再訪問服務端時會將cookie和請求一并提交
服務端會檢查cookie識別客戶端,并也可以根據需要修改cookie的內容
3.存在的問題
在分布式或集群系統中使用Session
假設現在服務器為了更好的承載和容災將系統做了分布式和集群,也就是有了N個服務端,那是不是每一個服務端都要具有對每一個客戶端的Session或者Cookie的識別能力呢?
這個可以使用Session共享的方式用于Session的識別,但是這并不能解決分布式系統下依然存在這個問題,因為通常每一個分布式系統都由不同的人負責或者跨網絡,甚至不同的公司,不可能全部都做session共享吧?這個時候就誕生了一個新的方式,使用Token
4.Token
- Token是服務端生成的一串字符串,以作客戶端進行請求的一個令牌。
執行步驟
用戶向統一的鑒權授權系統發起用戶名和密碼的校驗
校驗通過后會頒發一個Token,用戶就拿著頒發的Token去訪問其他三方系統
三方系統可以直接請求鑒權授權系統驗證當前Token的合法性,也可以根據對稱加密使用秘鑰解密Token以驗證合法性
.NET Core中鑒權
Authentication:
?鑒定身份信息,例如用戶有沒有登錄,用戶基本信息Authorization:
?判定用戶有沒有權限
1.NET Core鑒權授權基本概念
在NETCORE中鑒權授權是通過AuthenticationHttpContextExtensions擴展類中的實現的HttpContext的擴展方法來完成的
public static class AuthenticationHttpContextExtensions { public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) { context.RequestServices.GetRequiredService<IAuthenticationService>().SignInAsync(context, scheme, principal, properties); } }
它真正的核心在
Microsoft.AspNetCore.Authorization模塊,整個流程處理主要包含如下幾個關鍵類
IAuthenticationHandlerProvider
負責對用戶憑證的驗證,提供IAuthenticationHandler處理器給IAuthenticationService用于處理鑒權請求,當然可以自定義處理器
IAuthenticationSchemeProvider
選擇標識使用的是哪種認證方式
IAuthenticationService
提供鑒權統一認證的5個核心業務接口
public interface IAuthenticationService { //查詢鑒權 Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme); //登錄寫入鑒權憑證 Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties); //退出登錄清理憑證 Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties); Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties); Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties); }
在它的實現類AuthenticationService中的SignInAsync方法
配合IAuthenticationHandlerProvider 和IAuthenticationSchemeProvider得到一個IAuthenticationHandler,最終將鑒權寫入和讀取都由它完成
public virtual async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) { if (scheme == null) { //IAuthenticationSchemeProvider實例 var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync(); scheme = defaultScheme?.Name; } //IAuthenticationHandlerProvider實例獲取處理器 var handler = await Handlers.GetHandlerAsync(context, scheme); var signInHandler = handler as IAuthenticationSignInHandler; //各自的處理器handler //例如使用Cookie 就會注入一個CookieAuthenticationHandler //使用JWT 就注入一個JwtBearerHandler await signInHandler.SignInAsync(principal, properties); }
2.使用Cookie默認流程鑒權
- 使用中間件加入管道,用于找到鑒權HttpContext.AuthenticateAsync()
//核心源碼就是AuthenticationMiddleware中間件 app.UseAuthentication();
- 注入容器,將CookieAuthenticationHandler作為處理邏輯
services.AddAuthentication(options => { //CookieAuthenticationDefaults.AuthenticationScheme == "Cookies" options.DefaultAuthenticateScheme = "Cookies"; options.DefaultSignInScheme = "Cookies"; }).AddCookie();
- 在登錄時寫入憑證
Claims:一項信息,例如工牌的姓名是一個Claims ,工牌號碼也是一個Claims
ClaimsIdentity:一組Claims 組成的信息,就是一個用戶身份信息
ClaimsPrincipal:一個用戶有多個身份
AuthenticationTicket:用戶票據,用于包裹ClaimsPrincipal
[AllowAnonymous] public async Task<IActionResult> Login(string name, string password) { if(name!="Admin" && password!="000000") { var result = new JsonResult(new{ Result = false,Message = "登錄失敗"}); return result; } //Claims ? ClaimsIdentity ? ClaimsPrincipal var claimIdentity = new ClaimsIdentity("ClaimsIdentity"); claimIdentity.AddClaim(new Claim(ClaimTypes.Name, name)); claimIdentity.AddClaim(new Claim(ClaimTypes.Address, "地址信息")); AuthenticationProperties ap = new AuthenticationProperties(); ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimIdentity); await base.HttpContext.SignInAsync("Cookies",claimsPrincipal , ap) return new JsonResult(new{ Result = false,Message = "登錄成功"}); }
在其他控制器上標記[Authorize]特性,在訪問接口框架會自動進行鑒權并將身份信息寫入上下文
[AllowAnonymous]
:匿名可訪問[Authorize]
:必須登錄才可訪問
3.自定義IAuthenticationHandler
- 實現IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler三個接口
public class CoreAuthorizationHandler : IAuthenticationHandler ,IAuthenticationSignInHandler, IAuthenticationSignOutHandler { public AuthenticationScheme Scheme { get; private set; } protected HttpContext Context { get; private set; } public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) { Scheme = scheme; Context = context; return Task.CompletedTask; } public async Task<AuthenticateResult> AuthenticateAsync() { var cookie = Context.Request.Cookies["CustomCookie"]; if (string.IsNullOrEmpty(cookie)) { return AuthenticateResult.NoResult(); } AuthenticateResult result = AuthenticateResult .Success(Deserialize(cookie)); return await Task.FromResult(result); } public Task ChallengeAsync(AuthenticationProperties properties) { return Task.CompletedTask; } public Task ForbidAsync(AuthenticationProperties properties) { Context.Response.StatusCode = 403; return Task.CompletedTask; } public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) { var ticket = new AuthenticationTicket(user, properties, Scheme.Name); Context.Response.Cookies.Append("CoreAuthorizationHandlerCookies", Serialize(ticket)); return Task.CompletedTask; } public Task SignOutAsync(AuthenticationProperties properties) { Context.Response.Cookies.Delete("CoreAuthorizationHandlerCookies"); return Task.CompletedTask; } private AuthenticationTicket Deserialize(string content) { byte[] byteTicket = System.Text.Encoding.Default.GetBytes(content); return TicketSerializer.Default.Deserialize(byteTicket); } private string Serialize(AuthenticationTicket ticket) { //需要引入 Microsoft.AspNetCore.Authentication byte[] byteTicket = TicketSerializer.Default.Serialize(ticket); return Encoding.Default.GetString(byteTicket); } }
- 在容器中注冊自定義的Handler
services.AddAuthenticationCore(options => { options.AddScheme<CoreMvcAuthenticationHandler>("AuthenticationScheme", "AuthenticationScheme"); });
原文鏈接:https://www.cnblogs.com/yuxl01/p/15914376.html
相關推薦
- 2022-04-20 Python設計模式中的結構型橋接模式_python
- 2022-09-27 Kotlin淺析延遲初始化與密封類的實現方法_Android
- 2022-12-03 SQL?Server如何通過SQL語句直接操作另一臺服務器上的SQL?SERVER的數據_MsSql
- 2023-01-26 Android?源碼淺析RecyclerView?ItemAnimator_Android
- 2022-08-29 React合成事件原理解析_React
- 2022-05-31 Golang庫插件注冊加載機制的問題_Golang
- 2023-02-05 expect實現Linux自動登陸遠程機器腳本實例_Linux
- 2022-07-10 ENOENT讀取文件報錯(fs)
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支