從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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...