從0到1搭建許可權管理系統系列三 .net8 JWT創建Token並使用

来源:https://www.cnblogs.com/cyzf/p/18422784
-Advertisement-
Play Games

說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 結合上一篇文章使用,味道更佳:從0到1 ...


說明

    該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。

    該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。

    說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。

結合上一篇文章使用,味道更佳:從0到1搭建許可權管理系統系列二 .net8 使用JWT鑒權(附當前源碼)

有興趣的朋友,請關註我吧(*^▽^*)。

關註我,學不會你來打我

 創建Token

  創建token的因素(條件)有很多,在該篇文章中,採用jwt配置和用戶基本信息作為生成token的基本因素(讀者可根據系統,自由改變生成token因素)。

在JwtPlugInUnit.CS中創建2個方法(JwtPlugInUnit.CS在上一篇文章中有寫到)

方法一:PropValuesType方法
/// <summary>
/// 反射獲取欄位
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static IEnumerable<(string Name, object Value, string Type)> PropValuesType(this object obj)
{
    List<(string a, object b, string c)> result = new List<(string a, object b, string c)>();

    var type = obj.GetType();
    var props = type.GetProperties();
    foreach (var item in props)
    {
        result.Add((item.Name, item.GetValue(obj), item.PropertyType.Name));
    }
    return result;
}
上述方法:PropValuesType是通過反射獲取模型欄位和屬性。在本文章中,是為了提取登錄人員信息,編寫成List<Claim>,組成生成token的因素之一。
方法二:BuildToken方法
/// <summary>
/// 生成Token
/// </summary>
/// <param name="loginResult">登陸返回信息</param>
/// <returns></returns>
public static LoginOutPut BuildToken(LoginInput loginResult)
{
    LoginOutPut result = new LoginOutPut();
    //獲取配置
    var jwtsetting = AppSettingsPlugInUnit.GetNode<JwtSettingModel>("JwtSetting");

    //準備calims,記錄登錄信息
    var calims = loginResult.PropValuesType().Select(x => new Claim(x.Name, x.Value.ToString(), x.Type)).ToList();

    //創建header
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtsetting.SecurityKey));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var header = new JwtHeader(creds);

    //創建payload
    var payload = new JwtPayload(jwtsetting.Issuer, jwtsetting.Audience, calims, DateTime.Now, DateTime.Now.AddMinutes(jwtsetting.ExpireSeconds));

    //創建令牌 
    var token = new JwtSecurityToken(header, payload);
    var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
    result.ExpiresDate = token.ValidTo.AddHours(8).ToString();
    result.Token = tokenStr;
    result.UserName = loginResult.UserName;

    return result;
}

    上述方法:BuildToken是創建token的核心代碼,它通過用戶信息+jwt配置信息生成token,並返回token、用戶名、token過期時間等信息(讀者可以添加更多返回信息)。

    BuildToken中有2個模型,具體結構和位置如下:

創建Model類,用於存放系統中模型。

LoginInput模型結構如下:

/// <summary>
/// 登錄輸入模型
/// </summary>
public class LoginInput
{
    /// <summary>
    /// 用戶名
    /// </summary>
    public string? UserName { get; set; }

    /// <summary>
    /// 密碼
    /// </summary>
    public string? Password { get; set; }

}

LoginOutPut模型結構如下:

   /// <summary>
   /// 登錄輸入模型
   /// </summary>
   public class LoginOutPut
   {
       /// <summary>
       /// 用戶名
       /// </summary>
       public string? UserName { get; set; }

       /// <summary>
       /// 密碼
       /// </summary>
       public string? Password { get; set; }

       /// <summary>
       /// Token
       /// </summary>
       public string? Token { get; set; }

       /// <summary>
       /// Token過期時間
       /// </summary>
       public string? ExpiresDate { get; set; }

   }

做完以上操作,用戶就可以生成Token,但要把token運用到系統中,還需做以下操作。

創建模塊分組

  在ModeuleGroupEnum.cs中創建2個枚舉,具體如下

  說明:ModeuleGroupEnum.cs在從0到1搭建許可權管理系統系列一 .net8 使用Swagger(附當前源碼) 文章中有說明(或者關註我的微信公眾號)。

 /// <summary>
 /// 模塊分組
 /// </summary>
 public enum ModeuleGroupEnum
 {
     /// <summary>
     /// 系統菜單
     /// </summary>
     SysMenu = 1,

     /// <summary>
     /// 系統用戶
     /// </summary>
     SysUser = 2,

     /// <summary>
     /// 基礎
     /// </summary>
     Base = 3,
 }

  新增【系統用戶】、【基礎】2個枚舉。

創建新控制器

  創建2個控制器:BaseController和SysUserController,結構如下

  創建BaseController基礎控制器,它存在的作用,就是承擔系統中需要重寫方法和獲取用戶基本信息的橋梁。

代碼如下:

/// <summary>
/// 系統基礎模塊
/// </summary>
[ApiController]
[Route("api/[controller]/[action]")]
[ApiExplorerSettings(GroupName = nameof(ModeuleGroupEnum.Base))]
[Authorize]
public class BaseController : ControllerBase
{
    /// <summary>
    /// 獲取登陸人員信息
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public LoginOutPut GetLoginUserMsg()
    {
        StringValues s = new StringValues();
        var auth = Request.Headers.TryGetValue("Authorization", out s);
        if (string.IsNullOrWhiteSpace(s))
            throw new Exception("登錄信息失效");
        var token = new JwtSecurityTokenHandler().ReadJwtToken(s.ToString().Replace($"{JwtBearerDefaults.AuthenticationScheme} ", ""));
        LoginOutPut loginResult = new()
        {
            UserName = token.Claims.FirstOrDefault(f => f.Type == "UserName").Value,
            Password = Convert.ToString(token.Claims.FirstOrDefault(f => f.Type == "Password").Value),
        };
        return loginResult;

    }
}

解讀下該方法:通過獲取Headers中的Token,然後使用jwt反解析token獲取在BuildToken方法中記錄的用戶基本信息。

說明:控制器上方存在[Authorize],只要有控制器繼承基礎控制【BaseController】,那麼該控制器下的所有方法,都需要經過jwt驗證。如果某一個介面不需要token驗證,就在該介面上方添加 [AllowAnonymous]

  創建SysUserController控制器,並繼承BaseController控制器,它的作用就是承擔系統用戶的所有介面,具體代碼如下:

 /// <summary>
 /// 用戶模塊
 /// </summary>
 [ApiController]
 [Route("api/[controller]/[action]")]
 [ApiExplorerSettings(GroupName = nameof(ModeuleGroupEnum.SysUser))]
 public class SysUserController : BaseController
 {
     /// <summary>
     /// 獲取Token
     /// </summary>
     /// <param name="userName">用戶名</param>
     /// <param name="password">密碼</param>
     [HttpGet]
     [AllowAnonymous]
     public string GetToken(string userName, string password)
     {
         var loginResult = JwtPlugInUnit.BuildToken(new LoginInput { UserName = userName, Password = password });

         return loginResult.Token ?? string.Empty;
     }
 }

可以看到,該控制器下有2個介面,一個為獲取token介面(可同時作為登錄介面),一個為獲取登錄人員信息的介面(繼承BaseController下的GetLoginUserMsg()方法)。

做完以上操作,jwt中token驗證就完成啦,看一下成果。

不使用token訪問介面,不會成功

先獲取token

在添加使用token

點擊Authorize確定使用

再次訪問GetLoginUserMsg()介面,看下效果

回覆評論

上一篇文章:從0到1搭建許可權管理系統系列二 .net8 使用JWT鑒權(附當前源碼)得到了較多評論,有指正的、有疑問的。

首先感謝大家的閱讀,感謝大家的指正,也感謝大家的提問。

在這裡我針對些問題,回覆如下:

回覆一:

確實,在.net core 剛發佈的時候,所有人在微軟的引導下都對這一門的開源的框架,大家都叫它.net core ,它的出現也讓c#在生死的邊緣,獲得一線生機。但在.net core 3.1(應該)之後,就改名叫.net5 .net8等。

回覆二:

jwt它是輕量級的庫,所有它在這方面的處理,並不是很好。所以建議新增中間件驗證過期token或者把Token存到資料庫或緩存中,以此來操作複雜的鑒權驗證。

回覆三:

艾特這2位朋友,你要的來了,順便求關註博客園、關註微信公眾號,不錯過每次更新。

感謝你的耐心觀看。

如果對你有幫助,請關註我微信公眾號吧(*^▽^*)。

源代碼地址:https://gitee.com/yangguangchenjie/overall-auth2.0-web-api  

幫我Star,謝謝。

有興趣的朋友,請關註我微信公眾號吧(*^▽^*)。

關註我:一個全棧多端的寶藏博主,定時分享技術文章,不定時分享開源項目。關註我,帶你認識不一樣的程式世界




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文梳理總結了一些 Java 互聯網項目中常見的 Redis 緩存應用場景,例如常見的 String 類型 Key-Value、對時效性要求高的場景、Hash 結構的場景以及對實時性要求高的場景等,全面涵蓋了 Redis 中所有的 5 種基本類型。 ...
  • 在 Python 中,Zope 提供了一種機制來定義和實現介面。Zope 的介面模塊通常用於創建可重用的組件,並確保組件遵循特定的介面規範。 ...
  • Delete、Drop 和 Truncate delete、truncate 僅僅刪除表裡面的數據,drop會把表的結構也刪除 delete 是 DML 語句,操作完成後,可以回滾,truncate 和 drop 是 DDL 語句,刪除之後立即生效,不能回滾 執行效率:drop > truncate ...
  • python基礎 軟體下載 1.python下載安裝 點擊此鏈接進入官網windows下載地址 點擊箭頭處鏈接下載最新版本,進入頁面後下拉 根據你的機器下載對應版本,一般人使用的是X86架構windos系統,下載箭頭所指即可 若是不知道CPU架構,可見查看cpu架構,x86還是arm 下載後根據指引 ...
  • 實踐環境 Python 3.9.13 paho-mqtt 2.1.0 簡介 Eclipse Paho MQTT Python客戶端類庫實現了MQTT 協議版本 5.0, 3.1.1, 和3.1。 該類庫提供一個客戶端類,允許應用連接到MQTT代理併發布消息,訂閱主題並檢索發佈的消息。同時還提供了一個 ...
  • 前言 ConcurrentLinkedQueue是基於鏈接節點的無界線程安全隊列。此隊列按照FIFO(先進先出)原則對元素進行排序。隊列的頭部是隊列中存在時間最長的元素,而隊列的尾部則是最近添加的元素。新的元素總是被插入到隊列的尾部,而隊列的獲取操作(例如poll或peek)則是從隊列頭部開始。 與 ...
  • 先說一下我遇到問題,我的項目是NET8.0版本,在VisualStudio上可以正常運行與調試,但是在VSCode里可以正常跑但無論怎麼打斷點都不會進去,提示"還沒有為該文檔載入任何符號"。 其實最開始我以為是launch.json沒有配置好,搞了一上午換了很多種配置方式結果都沒有變。其中我創建新的 ...
  • 1.基礎階段 編程語言基礎(C#) 語法學習:掌握 C# 的基本語法,包括變數、數據類型(如整數、字元串、布爾等)、運算符、控制流語句(如 if-else、for、while 等)。 面向對象編程概念:深入理解面向對象的三大特性,即封裝、繼承、多態,學會定義類、對象、屬性、方法等,以及類的繼承和多態 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...