ASP.NET Core的JWT的實現(中間件).md

来源:https://www.cnblogs.com/xuhuale/archive/2019/03/17/10507241.html
-Advertisement-
Play Games

既然選擇了遠方,便只顧風雨兼程 __ HANS許 JWT(JSON Web Token) ASP.NET Core 的Middleware實現 引言:挺久沒更新了,之前做了Vue的系列,後面想做做服務端的系列,上下銜接,我們就講講WebApi(網路應用程式介面),介面免不了用戶認證,所以接下來我們的 ...


既然選擇了遠方,便只顧風雨兼程 __ HANS許

 

 

引言:挺久沒更新了,之前做了Vue的系列,後面想做做服務端的系列,上下銜接,我們就講講WebApi(網路應用程式介面),介面免不了用戶認證,所以接下來我們的主題系列文章便是“基於ASP.NET Core的用戶認證”,分為市面上流行的JWT(JSON WebToken)與OAuth2(開放授權)

JWT(JSON Web Token)

  • 什麼叫JWT
    JSON Web Token(JWT)是目前最流行的跨域身份驗證解決方案。

    一般來說,互聯網用戶認證是這樣子的。

    1、用戶向伺服器發送用戶名和密碼。
    2、伺服器驗證通過後,在當前對話(session)裡面保存相關數據,比如用戶角色、登錄時間等等。
    3、伺服器向用戶返回一個 session_id,寫入用戶的 Cookie。
    4、用戶隨後的每一次請求,都會通過 Cookie,將 session_id 傳回伺服器。
    5、伺服器收到 session_id,找到前期保存的數據,由此得知用戶的身份。

    伺服器需要保存session,做持久化,這種模式沒有分散式架構,無法支持橫向擴展,如果真的要的話就必須採用分散式緩存來進行管理Seesion。那JWT相反,它保存的是在客戶端,每次請求都將JWT代入伺服器,進行簽名,許可權驗證。JWT由客戶端請求,服務端生成,客戶端保存,服務端驗證。

  • JWT的原理與格式

    1. 原理
      在上面,我們也講過了,簡單的來說,我們將伺服器需要驗證我們的條件(賬戶,密碼等等),發給伺服器,伺服器認證通過,生成一個JSON對象返回給我們,例如下麵。當然,為了防止被篡改,所以我們會將對象加密,再次請求伺服器,需要將jwt放在請求頭部,傳遞給伺服器,來判斷許可權等等。

      1. "姓名": "張三"
      2. "角色": "管理員"
      3. "到期時間": "2018年7月1日0點0分" 
    2. 格式

      • 實際格式
      1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. 
      2. eyJBIjoiQUFBQSIsIkIiOiJCQkJCIiwiQyI6IkNDQ0MiLCJ1ZXIiOiJ4dWh1YWxlIiwib3BlbmlkIjoiNTE1NjEzMTM1MTYzMjEiLCJmZiI6ImRmc2RzZGZzZGZzZHMiLCJuYmYiOjE1NTIyMTE4NjAsImV4cCI6MTU1MjIxMzY2MH0. 
      3. 16m57YnnIcgIth25dwphQKPYuIq42BVmZV6LIBO7KDg 

      它是一個很長的字元串,中間用點(.)分隔成三個部分。註意,JWT內部是沒有換行的,這裡只是為了便於展示,將它寫成了幾行。JWT 的三個部分依次如下。

      • Header(頭部)
      • Payload(負載)
      • Signature(簽名)

      簡單講下,Header描述加密演算法與token類型,Payload描述的是實際需要傳遞的數據,如失效時間,簽發人等等,Signature描述的是一段對於前面兩部部分的簽名,當然秘鑰只有伺服器才知道。

簡單的介紹下JWT,更多的話,可以這邊文章看看。我們著重講下實現。

ASP.NET Core 的Middleware實現
  1. 創建JWT
    首先我們要先創建token,畢竟這個是最重要的。Core自帶JWT幫助類,所以我們按照幫助類的意思來寫個方法創建token。

    1. public string CreateJsonWebToken(Dictionary<string, string> payLoad) 
    2. if (string.IsNullOrWhiteSpace(setting.SecurityKey)) 
    3. throw new ArgumentNullException("JsonWebTokenSetting.securityKey"
    4. "securityKey為NULL或空字元串。請在\"appsettings.json\"配置\"JsonWebToken\"節點及其子節點\"securityKey\""); 
    5. var now = DateTime.UtcNow; 
    6.  
    7. // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims. 
    8. // You can add other claims here, if you want: 
    9. var claims = new List<Claim>(); 
    10. foreach (var key in payLoad.Keys) 
    11. var tempClaim = new Claim(key, payLoad[key]?.ToString()); 
    12. claims.Add(tempClaim); 
    13.  
    14. // Create the JWT and write it to a string 
    15. var jwt = new JwtSecurityToken( 
    16. issuer: null
    17. audience: null
    18. claims: claims, 
    19. notBefore: now, 
    20. expires: now.Add(TimeSpan.FromMinutes(setting.ExpiresMinute)), 
    21. signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(setting.SecurityKey)), SecurityAlgorithms.HmacSha256)); 
    22. var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); 
    23. return encodedJwt; 

    從方法我們看到,我們傳入的是負載這個片段,而失效時間與秘鑰我們是放在了appsettings.json來進行配置的。使用DI來獲取配置文件中的節點值。

  2. 編寫中間件
    我們都知道,中間件是Core的管道模型組成部分,所以我們在中間件做驗證,來判斷每次請求用戶是有有許可權是有該WebApi或者其他API。

    1. 中間件
      1. public JwtCustomerAuthorizeMiddleware(RequestDelegate next, IOptions<JsonWebTokenSetting> options, IJsonWebTokenValidate jsonWebTokenValidate, Func<Dictionary<string, string>, JsonWebTokenSetting, bool> validatePayLoad, List<string> anonymousPathList) 
      2. this._next = next; 
      3. this._setting = options.Value; 
      4. this._jsonWebTokenValidate = jsonWebTokenValidate; 
      5. this._validatePayLoad = validatePayLoad; 
      6. this._anonymousPathList = anonymousPathList; 
      7.  
      8. public async Task Invoke(HttpContext context) 
      9. //JsonWebTokenValidate 
      10. //若是路徑可以匿名訪問,直接跳過 
      11. if (_anonymousPathList.Contains(context.Request.Path.Value)) 
      12. //還未驗證 
      13. await _next(context); 
      14. return
      15. var result = context.Request.Headers.TryGetValue("Authorization", out StringValues authStr); 
      16. if (!result || string.IsNullOrEmpty(authStr.ToString())) 
      17. throw new UnauthorizedAccessException("未授權,請傳遞Header頭的Authorization參數。"); 
      18.  
      19. //進行驗證與自定義驗證 
      20. result = _jsonWebTokenValidate.Validate(authStr.ToString().Substring("Bearer ".Length).Trim() 
      21. , _setting, _validatePayLoad); 
      22. if (!result) 
      23. throw new UnauthorizedAccessException("驗證失敗,請查看傳遞的參數是否正確或是否有許可權訪問該地址。"); 
      24.  
      25. await _next(context); 

    從代碼來看,anonymousPathList是URL路徑,若是在這個List內的URL,便可直接跳過驗證,
    接著將authStrtoken代入驗證函數,validatePayLoad卻是我們自代入的委托函數,用於伺服器自定義驗證。

    1. 驗證
      驗證方法,我只是做了簽名驗證與時間驗證。並沒有定得死死的,讓用戶自由度的去進行驗證。
      1. public bool Validate(string encodeJwt, JsonWebTokenSetting setting, Func<Dictionary<string, string>, JsonWebTokenSetting, bool> validatePayLoad) 
      2. if (string.IsNullOrWhiteSpace(setting.SecurityKey)) 
      3. throw new ArgumentNullException("JsonWebTokenSetting.securityKey"
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 1、什麼是日誌? 簡單的說,日誌就是記錄程式的運行軌跡,方便查找關鍵信息,也方便快速定位解決問題。我們 Java 程式員在開發項目時都是依賴 Eclipse/ Idea 等開發工具的 Debug 調試功能來跟蹤解決 Bug,在開發環境可以這麼做,但項目發佈到了測試、生產環境呢?你有可能會說可以 ...
  • 本人經過2周的學習,成功搭建了認證伺服器,資源伺服器和客戶端 。下麵是本人對 oauth2的理解,以及spring-security的使用,如果理解錯誤的地方,還望指正。 現在代碼有點凌亂,過段時間會放到github上面的,本人會在代碼中添加詳細註釋,供學習交流使用 理解 1.認證伺服器 如抖音可以 ...
  • 參考資料 [1] @毛星雲【《Effective C 》提煉總結】 https://zhuanlan.zhihu.com/p/24553860 [2] 《C 捷徑教程》 [3] @flashyiyi【C NoGCString】 https://zhuanlan.zhihu.com/p/3552560 ...
  • 目前.NET Core 3.0的版本為.NET Core 3.0 Preview 3,對應ASP.NET Core 3.0 Preview 3。 ASP.NET Core 3.0 之後將不再支持.NET Framework,只運行在.NET Core 上面。 ASP.NET Core 3.0 現在已 ...
  • 各位好!這次要來替大家介紹的是如何在 .NET Web API 中自訂一個 ModelBinder 透過自定義的 ModelBinder 我們可以很簡單的將 QueryString 傳過來的參數綁定成我們設計好的 Complex Model 。 為什麼需要自行定義一個 ModelBinder 呢? ...
  • 剛通過開通寫博客的申請,向博客園的大佬致敬,由於一直以來都在網上搜索大家的思想,也有翻遍整個百度都有的找不到的時候,作為一個網民理應為互聯網貢獻一點東西。 下麵是我工作後受一個師傅的影響對資料庫訪問層的封裝,多年以來一直都在使用,用的特別爽,請看下麵的代碼: 第一步、需要編寫一個通用的用於查詢的數據 ...
  • [TOC] .NET MVC全局異常處理 一直知道有.NET有相關的配置,但沒有實際做過,以為改下設定就可以,結果實際使用的時候還是遇到不少問題,所以要記錄一下。 IIS配置 剛開始不想改程式代碼,所以直接就想到了IIS裡面的錯誤頁配置配置,一開始反覆測試,設置改了很多,但是沒有效果,後來發現是靜態 ...
  • 以前寫在CSDN上的文章。轉到博客園之後,打算把這個教程移過來,順便完善後面的教程。主要是在Asp.Net+EF6裡面使用cplex,完成一個最優生產計劃的決策。當時在查找如何在C#中引用cplex時,找到的大多是cplex在VS中的環境配置,大都還是以C++為例,而且覺得有些複雜。所以想寫一篇關於 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...