【從0開始.NET CORE認證】-4 開啟OAuth認證之JWT


系列

【從0開始.NET CORE認證】-1 認識認證和授權

【從0開始.NET CORE認證】-2 使用.Net Core Identity和EF Core

【從0開始.NET CORE認證】-3 聲明和策略授權

回顧

還是回到第三篇文章中,我們在第三篇文章簡單的介紹了一下以下內容

  1. 怎么樣結合Identity認證給IdentityUser簽發Claims
  2. 怎么樣使用基於策略的權限驗證
  3. 怎么樣使用基於角色的權限驗證
  4. 怎么樣對IdentityUser進行Claim操作

其實第三篇並沒有完全結束,只是沒寫完,有空再寫。基於策略的權限驗證能做很多有趣的事情。

但是本篇開始會開啟OAuth認證

本次主要寫一下內容

 

 

 OAuth介紹

大家可以去百度,但是百度來的一大堆專業詞匯,看的也非常迷惘!所以可以參考一下阮一峰大神的文章,關於解釋OAuth是什么

OAuth2.0的一個簡單解釋——阮一峰

我這里還是簡單的畫個圖方便大家理解

1.這幅圖就是傳統的送貨方式

 

 

 上面這幅圖會帶來什么問題?

  1. 業主告訴了快遞員密碼,在業主密碼沒更改的情況下,也就是說快遞員約等於業主。無論是否上下班都可以自由出入小區
  2. 快遞員泄露了密碼,會導致其他人也能冒充業主闖過小區門禁系統
  3. 業主如果每次收完貨就更改密碼,下次還是要把新密碼提供給快遞員。每次更改極其麻煩

所以為了解決問題,我們是不是中間加個流程,當快遞員需要送貨的時候,在小區門禁上提出申請,然后由業主同意,最后業主提供一個臨時密碼一樣的東西給快遞員,臨時密碼有有效期,1個小時就好了。這個問題是不是解決了

 

 

 增加了345步驟,既可以保證小區的安全性,又可以完成送貨

更多OAuth知識請參閱

RFC-6749文檔——英文版

RFC-6749文檔——中文版

JWT介紹

如果把上述流程應用到互聯網開發中,現在開發模式大多屬於前后端分離的狀態,如果前端想要拿到后端的數據,后端說:你憑什么拿數據!依據我們前三篇講的,我們可以用Cookies來證明自己。

但是Cookies有個局限就是無法應用於分布式場景。

所以引入了JWT的概念——JWT 全稱Json Web Token,是一串字符串

JWT分成三部分

  1. 頭部
  2. 載荷
  3. 簽名

頭部負責存儲簽名的算法和令牌的類型,載荷部分存儲用戶的個人信息。簽名部分是對頭部和載荷加密后生成的哈希字符。

頭部和載荷負責base64加密,簽名使用哈希,最終構成一個長度很長的字符串。

這個字符串就是快遞員送貨中的臨時密碼,在OAuth中也被稱為access_token

.Net Core Identity接入OAuth生成JWT

.Net Core Identity已經實現了OAuth的框架,我們就用.Net Core Identity來實現一下OAuth

新建一個項目,名稱為:OAuthServer,然后稍微修改一下使其成為一個MVC頁面,增加一個Index頁面和Secert頁面,其中Secert頁面需要授權訪問

 

 

使用JWT需要引用以下擴展包

Microsoft.AspNetCore.Authentication.JwtBearer

在添加一個Login接口,負責頒發jwt

 

 

 

 1 public IActionResult Login()
 2         {
 3             var claim = new[]
 4             {
 5                 new Claim(JwtRegisteredClaimNames.Sub,"test"),
 6                 new Claim("test","test123")
 7             };
 8 
 9             var keybytes = Encoding.UTF8.GetBytes(Constants.key);
10             var seckey = new SymmetricSecurityKey(keybytes);
11             var alorgthim = SecurityAlgorithms.HmacSha256;
12             var credential = new SigningCredentials(seckey, alorgthim);
13 
14             var token = new JwtSecurityToken(Constants.Issuer, Constants.Audiance, claim,
15                 notBefore: DateTime.Now,
16                 expires: DateTime.Now.AddHours(2),
17                 signingCredentials: credential
18                 );
19 
20             var access_token = new JwtSecurityTokenHandler().WriteToken(token);
21             return Ok(new { access_token });
22         }

其中Constrants類是我自定義的一個類

 1 public class Constants
 2     {
 3 
 4         public const string Issuer = "http://localhost:8266";
 5 
 6         public const string Audiance = "http://localhost:8266";
 7 
 8         public const string key = "private_key_should_set_longer";
 9 
10     }

 

 

運行,訪問/Home/Login接口

 

 

發現是可以生成JWT格式的Token了。

把拿到的token放到jwt.io解析一下,看下是什么東西

 

 可以看到,如我們上文介紹的一樣,分成三個部分,頭部,載荷和簽名

使用JWT訪問被保護的資源

這個時候需要使用一下測試工具POSTMAN,有關如果在http頭部請求加入驗證,請查閱百度,本處不再講述

用戶提交了一個jwt格式的token過來,我們肯定是需要進行核驗的,如果我們不進行核驗,用戶隨隨便便就提交過來,豈不是保護資源約等於沒保護?

在Startup.cs文件中修改一下代碼

 

 

 1 services.AddAuthentication("OAuth")
 2                 .AddJwtBearer("OAuth",config=> {
 3                     var keybytes = Encoding.UTF8.GetBytes(Constants.key);
 4                     var seckey = new SymmetricSecurityKey(keybytes);
 5                     config.TokenValidationParameters = new TokenValidationParameters
 6                     {
 7                         ValidIssuer = Constants.Issuer,
 8                         ValidAudience = Constants.Audiance,
 9                         IssuerSigningKey = seckey,
10                     };
11                 });

 

然后我們用postman測試一下

 

可以發現成功訪問。

把Token放到url連接里面

平常開發接口,有些時候為了方便,不會去對http的頭部進行設置。所以會選擇把token放到url參數里面,這種情況怎么處理呢?

只需要更改一下代碼就行了

 

 

 1 services.AddAuthentication("OAuth")
 2                 .AddJwtBearer("OAuth",config=> {
 3                     config.Events = new JwtBearerEvents()
 4                     {
 5                         OnMessageReceived = context =>
 6                         {
 7                             if (context.Request.Query.ContainsKey("access_token"))
 8                             {
 9                                 context.Token = context.Request.Query["access_token"];
10                             }
11                             return Task.CompletedTask;
12                         }
13                     };
14                     var keybytes = Encoding.UTF8.GetBytes(Constants.key);
15                     var seckey = new SymmetricSecurityKey(keybytes);
16                     config.TokenValidationParameters = new TokenValidationParameters
17                     {
18                         ValidIssuer = Constants.Issuer,
19                         ValidAudience = Constants.Audiance,
20                         IssuerSigningKey = seckey,
21                     };
22                 });

只需要偵聽OnMessageReceived事件,當請求的url中包含access_token就把它的值賦給上下文中的token

運行看下:

 

 可以發現,成功訪問。

結束

好了,本章的JWT知識就到這里。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM