.NET?CORE?鑒權(quán)的實(shí)現(xiàn)示例
基礎(chǔ)信息
1.什么是鑒權(quán)授權(quán)?
- 鑒權(quán)是驗(yàn)證用戶是否擁有訪問系統(tǒng)的權(quán)利,授權(quán)是判斷用戶是否有權(quán)限做一些其他操作。
2.傳統(tǒng)的Session 和Cookie
- 主要用于無狀態(tài)請求下的的用戶身份識別,只不過Session將信息存儲在服務(wù)端,Cookie將信息存儲在客戶端。
Session
在客戶端第一次進(jìn)行訪問時,服務(wù)端會生成一個Session id返回到客戶端
客戶端將Session id存儲在本地后續(xù)每一次請求都帶上這個id
服務(wù)端從接收到的請求中根據(jù)Session id在自己存儲的信息中識別客戶端
Cookie
在客戶端訪問服務(wù)器時,服務(wù)端會在響應(yīng)中頒發(fā)一個Cookie
客戶端會把cookie存儲,當(dāng)再訪問服務(wù)端時會將cookie和請求一并提交
服務(wù)端會檢查cookie識別客戶端,并也可以根據(jù)需要修改cookie的內(nèi)容
3.存在的問題
在分布式或集群系統(tǒng)中使用Session
假設(shè)現(xiàn)在服務(wù)器為了更好的承載和容災(zāi)將系統(tǒng)做了分布式和集群,也就是有了N個服務(wù)端,那是不是每一個服務(wù)端都要具有對每一個客戶端的Session或者Cookie的識別能力呢?
這個可以使用Session共享的方式用于Session的識別,但是這并不能解決分布式系統(tǒng)下依然存在這個問題,因?yàn)橥ǔC恳粋€分布式系統(tǒng)都由不同的人負(fù)責(zé)或者跨網(wǎng)絡(luò),甚至不同的公司,不可能全部都做session共享吧?這個時候就誕生了一個新的方式,使用Token
4.Token
- Token是服務(wù)端生成的一串字符串,以作客戶端進(jìn)行請求的一個令牌。

執(zhí)行步驟
用戶向統(tǒng)一的鑒權(quán)授權(quán)系統(tǒng)發(fā)起用戶名和密碼的校驗(yàn)
校驗(yàn)通過后會頒發(fā)一個Token,用戶就拿著頒發(fā)的Token去訪問其他三方系統(tǒng)
三方系統(tǒng)可以直接請求鑒權(quán)授權(quán)系統(tǒng)驗(yàn)證當(dāng)前Token的合法性,也可以根據(jù)對稱加密使用秘鑰解密Token以驗(yàn)證合法性
.NET Core中鑒權(quán)
Authentication:鑒定身份信息,例如用戶有沒有登錄,用戶基本信息Authorization:判定用戶有沒有權(quán)限
1.NET Core鑒權(quán)授權(quán)基本概念
在NETCORE中鑒權(quán)授權(quán)是通過AuthenticationHttpContextExtensions擴(kuò)展類中的實(shí)現(xiàn)的HttpContext的擴(kuò)展方法來完成的
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模塊,整個流程處理主要包含如下幾個關(guān)鍵類
IAuthenticationHandlerProvider
負(fù)責(zé)對用戶憑證的驗(yàn)證,提供IAuthenticationHandler處理器給IAuthenticationService用于處理鑒權(quán)請求,當(dāng)然可以自定義處理器
IAuthenticationSchemeProvider
選擇標(biāo)識使用的是哪種認(rèn)證方式
IAuthenticationService
提供鑒權(quán)統(tǒng)一認(rèn)證的5個核心業(yè)務(wù)接口
public interface IAuthenticationService
{
//查詢鑒權(quán)
Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme);
//登錄寫入鑒權(quán)憑證
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);
}
在它的實(shí)現(xiàn)類AuthenticationService中的SignInAsync方法
配合IAuthenticationHandlerProvider 和IAuthenticationSchemeProvider得到一個IAuthenticationHandler,最終將鑒權(quán)寫入和讀取都由它完成
public virtual async Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
{
if (scheme == null)
{
//IAuthenticationSchemeProvider實(shí)例
var defaultScheme = await Schemes.GetDefaultSignInSchemeAsync();
scheme = defaultScheme?.Name;
}
//IAuthenticationHandlerProvider實(shí)例獲取處理器
var handler = await Handlers.GetHandlerAsync(context, scheme);
var signInHandler = handler as IAuthenticationSignInHandler;
//各自的處理器handler
//例如使用Cookie 就會注入一個CookieAuthenticationHandler
//使用JWT 就注入一個JwtBearerHandler
await signInHandler.SignInAsync(principal, properties);
}
2.使用Cookie默認(rèn)流程鑒權(quán)
- 使用中間件加入管道,用于找到鑒權(quán)HttpContext.AuthenticateAsync()
//核心源碼就是AuthenticationMiddleware中間件 app.UseAuthentication();
- 注入容器,將CookieAuthenticationHandler作為處理邏輯
services.AddAuthentication(options =>
{
//CookieAuthenticationDefaults.AuthenticationScheme == "Cookies"
options.DefaultAuthenticateScheme = "Cookies";
options.DefaultSignInScheme = "Cookies";
}).AddCookie();
- 在登錄時寫入憑證
Claims:一項(xiàng)信息,例如工牌的姓名是一個Claims ,工牌號碼也是一個ClaimsClaimsIdentity:一組Claims 組成的信息,就是一個用戶身份信息ClaimsPrincipal:一個用戶有多個身份AuthenticationTicket:用戶票據(jù),用于包裹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 = "登錄成功"});
}
在其他控制器上標(biāo)記[Authorize]特性,在訪問接口框架會自動進(jìn)行鑒權(quán)并將身份信息寫入上下文
[AllowAnonymous]:匿名可訪問[Authorize]:必須登錄才可訪問
3.自定義IAuthenticationHandler
- 實(shí)現(xiàn)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");
});到此這篇關(guān)于.NET CORE 鑒權(quán)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān).NET CORE 鑒權(quán) 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一步步教會你微信小程序的登錄鑒權(quán)
- SpringBoot集成Spring Security用JWT令牌實(shí)現(xiàn)登錄和鑒權(quán)的方法
- nuxt框架中路由鑒權(quán)之Koa和Session的用法
- React路由鑒權(quán)的實(shí)現(xiàn)方法
- Vue中axios的封裝(報錯、鑒權(quán)、跳轉(zhuǎn)、攔截、提示)
- 前后端常見的幾種鑒權(quán)方式(小結(jié))
- Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例
- SpringCloud Zuul過濾器實(shí)現(xiàn)登陸鑒權(quán)代碼實(shí)例
- springmvc用于方法鑒權(quán)的注解攔截器的解決方案代碼
相關(guān)文章
AspNetPager+GridView實(shí)現(xiàn)分頁的實(shí)例代碼
AspNetPager+GridView實(shí)現(xiàn)分頁的實(shí)例代碼,需要的朋友可以參考一下2013-03-03
VS2010、VS2008等項(xiàng)目的默認(rèn)瀏覽器修改方法(圖文)
默認(rèn)情況下,VS會使用操作系統(tǒng)的默認(rèn)瀏覽器,但我在調(diào)試 ASP.NET 程序時更偏向于使用IE瀏覽器,下面與大家分享下VS2010、VS2008等項(xiàng)目的默認(rèn)瀏覽器的修改方法2013-05-05
IE和火狐中模仿Click事件及提交到新窗口總結(jié)(asp.net)
在程序中去模擬一個click事件是可以的,如果這個click事件是來自<a>標(biāo)簽的,那如果希望得到單擊按鈕的效果,IE可以,但火狐無法實(shí)現(xiàn)2012-01-01
.NetCore使用過濾器實(shí)現(xiàn)登錄權(quán)限認(rèn)證的方法小結(jié)
這篇文章主要介紹了.NetCore使用過濾器實(shí)現(xiàn)登錄權(quán)限認(rèn)證幾種方式總結(jié),主要包括自定義行為過濾器在OnActionExecuting中實(shí)現(xiàn),自定義身份驗(yàn)證過濾器,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-06-06
.net core 讀取本地指定目錄下的文件的實(shí)例代碼
這篇文章主要介紹了.net core 讀取本地指定目錄下的文件的實(shí)例代碼,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下2018-09-09
Repeater的FooterTemplate顯示某列總計(jì)思路與代碼
在Repeater的FooterTemplate顯示某列總計(jì),接下來與大家分享詳細(xì)的實(shí)現(xiàn)方案,感興趣的各位可以參考下哈2013-03-03
Ext.net中的MessageBox的簡單應(yīng)用實(shí)現(xiàn)代碼
今天在項(xiàng)目中要用到簡單的MessageBox的使用。在Ext.net中沒有Winform那么簡單,直接寫MessageBox.show()的方法。于是就去examples.ext.net的例子網(wǎng)站找,想找到個實(shí)際能用的2012-03-03
ASP.NET小結(jié)之MVC, MVP, MVVM比較以及區(qū)別(二)
上一篇得到大家的關(guān)注,非常感謝。由于自己對于這些模式的理解也是有限,對于MVC,MVP,MVVM這些模式的比較,是結(jié)合自己的理解,一些地方不一定準(zhǔn)確,需要的朋友可以參考下2014-05-05
asp.net 關(guān)于字符串內(nèi)范圍截取的一點(diǎn)方法總結(jié)
前兩天有一位網(wǎng)友提出了一個字符串內(nèi)截取字符串的問題,除了用普通的字符串截取的方式外,我推薦的是用LINQ方式來截取。兩者實(shí)際上差別不是很大,都是采用字符串截取方式,但后者從寫法和觀察效果會比前者簡單實(shí)用得多。2010-02-02
輕量級ORM框架Dapper應(yīng)用支持操作函數(shù)和事物
這篇文章介紹了Dapper支持操作函數(shù)和事物的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03

