一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - 淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

2020-06-28 14:35癡者工良 ASP.NET教程

這篇文章主要介紹了淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1,快速實現(xiàn)授權(quán)驗證

什么是 JWT ?為什么要用 JWT ?JWT 的組成?

這些百度可以直接找到,這里不再贅述。

實際上,只需要知道 JWT 認(rèn)證模式是使用一段 Token 作為認(rèn)證依據(jù)的手段。

我們看一下 Postman 設(shè)置 Token 的位置。

淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

那么,如何使用 C# 的 HttpClient 訪問一個 JWT 認(rèn)證的 WebAPI 呢?

淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

下面來創(chuàng)建一個 ASP.NET Core 項目,嘗試添加 JWT 驗證功能。

1.1 添加 JWT 服務(wù)配置

在 Startup.cs 的 ConfigureServices 方法中,添加一個服務(wù)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 設(shè)置驗證方式為 Bearer Token
 // 你也可以添加 using Microsoft.AspNetCore.Authentication.JwtBearer;
 // 使用 JwtBearerDefaults.AuthenticationScheme 代替 字符串 "Brearer"
 services.AddAuthentication("Bearer")
  .AddJwtBearer(options =>
  {
   options.TokenValidationParameters = new TokenValidationParameters
   {
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234")), // 加密解密Token的密鑰
 
    // 是否驗證發(fā)布者
    ValidateIssuer = true,
    // 發(fā)布者名稱
    ValidIssuer = "server",
 
    // 是否驗證訂閱者
    // 訂閱者名稱
    ValidateAudience = true,
    ValidAudience = "client007",
 
    // 是否驗證令牌有效期
    ValidateLifetime = true,
    // 每次頒發(fā)令牌,令牌有效時間
    ClockSkew = TimeSpan.FromMinutes(120)
   };
  });

修改 Configure 中的中間件

?
1
2
3
4
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();  // 注意這里
app.UseAuthorization();

就是這么簡單,通過以上設(shè)置,要求驗證請求是否有權(quán)限。

1.2 頒發(fā) Token

頒發(fā)的 Token ,ASP.NET Core 不會保存。

ASP.NET Core 啟用了 Token 認(rèn)證,你隨便將生成 Token 的代碼放到不同程序的控制臺,只要密鑰和 Issuer 和 Audience 一致,生成的 Token 就可以登錄這個 ASP.NET Core。

也就是說,可以隨意創(chuàng)建控制臺程序生成 Token,生成的 Token 完全可以登錄 ASP.NET Core 程序。

至于原因,我們后面再說,

在 Program.cs 中,添加一個這樣的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static void ConsoleToke()
{
 
 // 定義用戶信息
 var claims = new Claim[]
 {
  new Claim(ClaimTypes.Name, "癡者工良"),
  new Claim(JwtRegisteredClaimNames.Email, "[email protected]"),
 };
 
 // 和 Startup 中的配置一致
 SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdABCD1234abcdABCD1234"));
 
 JwtSecurityToken token = new JwtSecurityToken(
  issuer: "server",
  audience: "client007",
  claims: claims,
  notBefore: DateTime.Now,
  expires: DateTime.Now.AddMinutes(30),
  signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
 );
 
 string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
 Console.WriteLine(jwtToken);
}

Main() 中,調(diào)用此方法

?
1
2
3
4
5
public static void Main(string[] args)
 {
  ConsoleToke();
  CreateHostBuilder(args).Build().Run();
 }

1.3 添加 API訪問

我們添加一個 API。

[Authorize] 特性用于標(biāo)識此 Controller 或 Action 需要使用合規(guī)的 Token 才能登錄。

?
1
2
3
4
5
6
7
8
9
10
11
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
 public string Get()
 {
  Console.WriteLine(User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name));
  return "訪問成功";
 }
}

然后啟動 ASP.NET Core,在 Postman 測試 訪問 https://localhost/api/home。

淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

發(fā)現(xiàn)報 401 (無權(quán)限)狀態(tài)碼,這是因為請求時不攜帶令牌,會導(dǎo)致不能訪問 API。

從控制臺終端復(fù)制生成的 Token 碼,復(fù)制到 Postman 中,再次訪問,發(fā)現(xiàn)響應(yīng)狀態(tài)碼為 200,響應(yīng)成功。

淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理

ASP.NET Core 自帶 jwt 認(rèn)證大概就是這樣。

那么,ASP.NET Core 內(nèi)部是如何實現(xiàn)的呢?又有哪些特性哪些坑呢?請往下看~

2,探究授權(quán)認(rèn)證中間件

在上面的操作中,我們在管道配置了兩個中間件。

?
1
2
app.UseAuthentication();
app.UseAuthorization();

app.UseAuthentication(); 的作用是通過 ASP.NET Core 中配置的授權(quán)認(rèn)證,讀取客戶端中的身份標(biāo)識(Cookie,Token等)并解析出來,存儲到 context.User 中。

app.UseAuthorization(); 的作用是判斷當(dāng)前訪問 Endpoint (Controller或Action)是否使用了 [Authorize]以及配置角色或策略,然后校驗 Cookie 或 Token 是否有效。

使用特性設(shè)置相應(yīng)通過認(rèn)證才能訪問,一般有以下情況。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 不適用特性,可以直接訪問
public class AController : ControllerBase
{
 public string Get() { return "666"; }
}
 
/// <summary>
/// 整個控制器都需要授權(quán)才能訪問
/// </summary>
[Authorize]
public class BController : ControllerBase
{
 public string Get() { return "666"; }
}
 
public class CController : ControllerBase
{
 // 只有 Get 需要授權(quán)
 [Authorize]
 public string Get() { return "666"; }
 public string GetB() { return "666"; }
}
 
/// <summary>
/// 整個控制器都需要授權(quán),但 Get 不需要
/// </summary>
[Authorize]
public class DController : ControllerBase
{
 [AllowAnonymous]
 public string Get() { return "666"; }
}

2.1 實現(xiàn) Token 解析

至于 ASP.NET Core 中,app.UseAuthentication();app.UseAuthorization(); 的源代碼各種使用了一個項目來寫,代碼比較多。要理解這兩個中間件的作用,我們不妨來手動實現(xiàn)他們的功能。

解析出的 Token 是一個 ClaimsPrincipal 對象,將此對象給 context.User 賦值,然后在 API 中可以使用 User 實例來獲取用戶的信息。

在中間件中,使用下面的代碼可以獲取客戶端請求的 Token 解析。

?
1
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme);

那么,我們?nèi)绾问止脑?Http 請求中,解析出來呢?且看我慢慢來分解步驟。

首先創(chuàng)建一個 TestMiddleware 文件,作為中間件使用。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestMiddleware
{
 private readonly RequestDelegate _next;
 jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
 public TestMiddleware(RequestDelegate next)
 {
  _next = next;
 }
 public async Task Invoke(HttpContext context)
 {
  if (context == null)
  {
   throw new ArgumentNullException(nameof(context));
  }
 
  // 我們寫代碼的區(qū)域
 
 
  // 我們寫代碼的區(qū)域
  await _next(context);
 }
}

2.1.1 從 Http 中獲取 Token

下面代碼可以中 http 請求中,取得頭部的 Token 。

當(dāng)然,客戶端可能沒有攜帶 Token,可能獲取結(jié)果為 null ,自己加個判斷。

貼到代碼區(qū)域。

?
1
string tokenStr = context.Request.Headers["Authorization"].ToString();

Header 的 Authorization 鍵,是由 Breaer {Token}組成的字符串。

2.1.2 判斷是否為有效令牌

拿到 Token 后,還需要判斷這個 Token 是否有效。

因為 Authorization 是由 Breaer {Token}組成,所以我們需要去掉前面的 Brear 才能獲取 Token。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
 /// Token是否是符合要求的標(biāo)準(zhǔn) Json Web 令牌
 /// </summary>
 /// <param name="tokenStr"></param>
 /// <returns></returns>
 public bool IsCanReadToken(ref string tokenStr)
 {
  if (string.IsNullOrWhiteSpace(tokenStr) || tokenStr.Length < 7)
   return false;
  if (!tokenStr.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))
   return false;
  tokenStr = tokenStr.Substring(7);
  bool isCan = jwtSecurityTokenHandler.CanReadToken(tokenStr);
 
  return isCan;
 }

獲得 Token 后,通過 JwtSecurityTokenHandler.CanReadToken(tokenStr); 來判斷 Token 是否符合協(xié)議規(guī)范。

將下面判斷貼到代碼區(qū)域。

?
1
2
if (!IsCanReadToken(ref tokenStr))
    return ;

2.1.3 解析 Token

下面代碼可以將 Header 的 Authorization 內(nèi)容轉(zhuǎn)為 JwtSecurityToken 對象。

(截取字符串的方式很多種,喜歡哪個就哪個。。。)

?
1
2
3
4
5
6
7
8
9
10
/// <summary>
 /// 從Token解密出JwtSecurityToken,JwtSecurityToken : SecurityToken
 /// </summary>
 /// <param name="tokenStr"></param>
 /// <returns></returns>
 public JwtSecurityToken GetJwtSecurityToken(string tokenStr)
 {
  var jwt = jwtSecurityTokenHandler.ReadJwtToken(tokenStr);
  return jwt;
 }

不過這個 GetJwtSecurityToken 不是我們關(guān)注的內(nèi)容,我們是要獲取 Claim。

JwtSecurityToken.Claims

將下面代碼貼到代碼區(qū)域

?
1
2
JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);
IEnumerable<Claim> claims = jst.Claims;

2.1.4 生成 context.User

context.User 是一個 ClaimsPrincipal 類型,我們通過解析出的 Claim,生成 ClaimsPrincipal。

?
1
2
3
4
5
JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);
IEnumerable<Claim> claims = jst.Claims;
 
List<ClaimsIdentity> ci = new List<ClaimsIdentity>() { new ClaimsIdentity(claims) };
context.User = new ClaimsPrincipal(ci);

最終的代碼塊是這樣的

?
1
2
3
4
5
6
7
8
9
10
11
12
// 我們寫代碼的區(qū)域
string tokenStr = context.Request.Headers["Authorization"].ToString();
string requestUrl = context.Request.Path.Value;
if (!IsCanReadToken(ref tokenStr))
 return;
JwtSecurityToken jst = GetJwtSecurityToken(tokenStr);
IEnumerable<Claim> claims = jst.Claims;
List<ClaimsIdentity> ci = new List<ClaimsIdentity>() { new ClaimsIdentity(claims) };
 
context.User = new ClaimsPrincipal(ci);
var x = new ClaimsPrincipal(ci);
// 我們寫代碼的區(qū)域

2.2 實現(xiàn)校驗認(rèn)證

app.UseAuthentication(); 的大概實現(xiàn)過程已經(jīng)做出了說明,現(xiàn)在我們來繼續(xù)實現(xiàn) app.UseAuthorization(); 中的功能。

繼續(xù)使用上面的中間件,在原代碼塊區(qū)域添加新的區(qū)域。

?
1
2
3
// 我們寫代碼的區(qū)域
 
// 我們寫的代碼塊

 22.2.1 Endpoint

Endpoint 標(biāo)識了一個 http 請求所訪問的路由信息和 Controller 、Action 及其特性等信息。

[Authorize] 特性繼承了 IAuthorizeData[AllowAnonymous] 特性繼承了 IAllowAnonymous

以下代碼可以獲取所訪問的節(jié)點信息。

?
1
var endpoint = context.GetEndpoint();

那么如何判斷所訪問的 Controller 和 Action 是否使用了認(rèn)證相關(guān)的特性?

?
1
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();

Metadata 是一個 ASP.NET Core 實現(xiàn)的集合對象,GetOrderedMetadata<T> 可以找出需要的特性信息。

這個集合不會區(qū)分是 Contrller 還是 Action 的 [Authorize] 特性。

那么判斷 是否有 [AllowAnonymous] 特性,可以這樣使用。

?
1
2
3
4
5
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
   {
    await _next(context);
    return;
   }

到此這篇關(guān)于淺談ASP.NET Core 中jwt授權(quán)認(rèn)證的流程原理的文章就介紹到這了,更多相關(guān)ASP.NET Core jwt授權(quán)認(rèn)證內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.cnblogs.com/whuanle/p/12497614.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 青草园网站在线观看 | 小草视频免费观看在线 | 天堂网在线网站成人午夜网站 | 婷婷精品 | 亚洲一区二区福利视频 | 久久99re热在线观看视频 | 天美传媒tm0087 | 免费一级生活片 | 日韩伦理在线免费观看 | 妇乱子伦激情 | 色婷婷在线播放 | 日韩精品一区二区三区老鸭窝 | 久热这里只有精品99国产6 | 男女被爆动漫羞羞动漫 | 美女的让男人桶爽免费看 | 久久久免费观成人影院 | 国产成人精视频在线观看免费 | 接吻吃胸摸下面啪啪教程 | bl超h 高h 污肉快穿np | 日本老师动漫 | 久久夜色噜噜噜亚洲AV0000 | 热99这里有精品综合久久 | 亚洲AV精品无码喷水直播间 | 日本高清中文字幕一区二区三区 | 亚洲精品视频在线 | 51精品 | 教室里的激情电影 | 俄罗斯大逼 | 日韩亚洲人成在线综合 | 欧美老少 | 99久久国产综合精品女不卡 | 美女视频黄a| v视界影院成片 | 黑人异族日本人hd | 大伊香蕉在线精品不卡视频 | 精品视频久久久久 | 日韩精品一区二区三区老鸭窝 | sex5·性屋娱乐 | 欧美性理论片在线观看片免费 | 超级碰碰免费视频 | 美女无内裤下部黄 |