在 .NET 8.0 中實現 JWT 刷新令牌

介紹

在 Web 開發領域,安全是重中之重。JSON Web Tokens (JWT) 已成為在各方之間安全傳輸信息的熱門選擇。然而,在 JWT 過期后,如何維護用戶會話并避免頻繁登錄至關重要。這正是 JWT 刷新令牌應運而生的地方。

在本文中,我們將指導您在 .NET 8.0 環境中實現 JWT 刷新令牌。我們將通過完整的示例介紹每個步驟,以確保清晰地理解整個過程。

JWT 和刷新令牌

JSON Web Tokens (JWT) 由三部分組成:標頭、有效負載和簽名。它們經過數字簽名以驗證其真實性,并包含聲明,這些聲明是關于實體(用戶)和其他數據的聲明。JWT 具有到期時間 (exp),到期后將被視為無效。刷新令牌用于在原始令牌到期后獲取新的 JWT,而無需用戶重新輸入其憑據。

設置.NET項目

讓我們使用 JWT 和刷新令牌創建一個簡單的身份驗證系統。

首先,確保您已安裝必要的包(System.IdentityModel.Tokens.Jwt 和 Microsoft.AspNetCore.Authentication.JwtBearer)。

模型

創建兩個模型來表示登錄請求和包含令牌的響應。

// LoginModel.cs
public class LoginModel
{
public string Username { get; set; }
public string Password { get; set; }
}

// TokenResponse.cs
public class TokenResponse
{
public string AccessToken { get; set; }
public string RefreshToken { get; set; }
}

授權控制器

創建一個負責處理身份驗證和令牌生成的 AuthController。

[ApiController]
[Route("[controller]")]
public class AuthController : ControllerBase
{
private readonly IConfiguration _config;
private readonly IUserService _userService;

? ? public AuthController(IConfiguration config, IUserService userService)
{
_config = config;
_userService = userService;
}

? ? [HttpPost("login")]
public IActionResult Login(LoginModel loginModel)
{
// Authenticate user
var user = _userService.Authenticate(loginModel.Username, loginModel.Password);

? ? ? ? if (user == null)
return Unauthorized();

? ? ? ? // Generate tokens
var accessToken = TokenUtils.GenerateAccessToken(user, _config["Jwt:Secret"]);
var refreshToken = TokenUtils.GenerateRefreshToken();

? ? ? ? // Save refresh token (for demo purposes, this might be stored securely in a database)
// _userService.SaveRefreshToken(user.Id, refreshToken);

? ? ? ? var response = new TokenResponse
{
AccessToken = accessToken,
RefreshToken = refreshToken
};

? ? ? ? return Ok(response);
}

? ? [HttpPost("refresh")]
public IActionResult Refresh(TokenResponse tokenResponse)
{
// For simplicity, assume the refresh token is valid and stored securely
// var storedRefreshToken = _userService.GetRefreshToken(userId);

? ? ? ? // Verify refresh token (validate against the stored token)
// if (storedRefreshToken != tokenResponse.RefreshToken)
// ? ?return Unauthorized();

? ? ? ? // For demonstration, let's just generate a new access token
var newAccessToken = TokenUtils.GenerateAccessTokenFromRefreshToken(tokenResponse.RefreshToken, _config["Jwt:Secret"]);

? ? ? ? var response = new TokenResponse
{
AccessToken = newAccessToken,
RefreshToken = tokenResponse.RefreshToken // Return the same refresh token
};

? ? ? ? return Ok(response);
}
}

Token Utility

創建一個實用程序類 TokenUtils 來處理令牌的生成和驗證。

public static class TokenUtils
{
public static string GenerateAccessToken(User user, string secret)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(secret);

? ? ? ? var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
Expires = DateTime.UtcNow.AddMinutes(15), // Token expiration time
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};

? ? ? ? var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}

? ? public static string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}

? ? public static string GenerateAccessTokenFromRefreshToken(string refreshToken, string secret)
{
// Implement logic to generate a new access token from the refresh token
// Verify the refresh token and extract necessary information (e.g., user ID)
// Then generate a new access token

? ? ? ? // For demonstration purposes, return a new token with an extended expiry
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(secret);

? ? ? ? var tokenDescriptor = new SecurityTokenDescriptor
{
Expires = DateTime.UtcNow.AddMinutes(15), // Extend expiration time
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};

? ? ? ? var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}

用戶服務(示例)

為了演示目的,這里有一個提供用戶身份驗證的簡單 UserService。

public interface IUserService
{
User Authenticate(string username, string password);
// void SaveRefreshToken(int userId, string refreshToken);
// string GetRefreshToken(int userId);
}

public class UserService : IUserService
{
private readonly List<User> _users = new List<User>
{
new User { Id = 1, Username = "user1", Password = "password1" }
};

? ? public User Authenticate(string username, string password)
{
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
return user;
}

? ? // For demo purposes - methods to save and retrieve refresh tokens
}

用戶模型(示例)

創建一個簡單的用戶模型。

public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}

啟動配置

在您的 Startup.cs 中,配置 JWT 身份驗證。

public void ConfigureServices(IServiceCollection services)
{
// ...

? ? var secret = Configuration["Jwt:Secret"];
var key = Encoding.ASCII.GetBytes(secret);

? ? services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});

? ? // ...
}

重要提示

這是一個用于演示的基本實現。在生產環境中,您應該增強安全性,安全地處理令牌存儲,并實現適當的驗證和錯誤處理。
為了更好的安全性,請考慮使用 IdentityServer4 庫或其他成熟的身份驗證解決方案。

結論

在 .NET 8.0 中實現 JWT 刷新令牌涉及配置身份驗證中間件、在身份驗證時生成令牌以及根據需要刷新過期令牌。此過程允許無縫令牌更新,而無需用戶重復登錄,從而增強了安全性。

記住要安全地處理令牌存儲并實施適當的驗證邏輯,以確保身份驗證系統的安全性和完整性。

如果您喜歡此文章,請收藏、點贊、評論,謝謝,祝您快樂每一天。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97183.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97183.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97183.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入解析 git push 命令

1. 基礎語法 git push 的基本語法如下: git push <遠程倉庫名> <本地分支名>:<遠程分支名> [選項]<遠程倉庫名>: 通常是 origin(默認的遠程倉庫名稱)。 <本地分支名>:<遠程分支名>: 指定要推送的本地分支以及目標遠程分支。如果省略遠…

UI彈出動畫

簡介的UI彈出動畫 使用方式很簡單 掛載到需要彈出的目標 即可 using UnityEngine; using DG.Tweening; using Unity.VisualScripting;/// <summary>/// 簡潔的UI動畫腳本/// 直接掛載到UI組件上&#xff0c;調用Play()播放縮放彈出動畫/// </summary>public class …

PostgreSQL診斷系列(6/6):配置項全景解析——打造你的專屬優化清單

&#x1f517; 作為《PostgreSQL診斷系列》的收官之作&#xff0c;今天我們系統梳理 postgresql.conf 中的核心參數&#xff0c;將前5篇的“診斷”轉化為“調優”&#xff0c;打造一套生產環境專屬的配置模板。 你是否&#xff1a; 不知道哪些參數該調&#xff1f;害怕調錯導致…

Flink Slot 不足導致任務Pending修復方案

當前有3個虛擬機節點&#xff0c;每個節點配置的slot節點數量是4&#xff0c;${FLINK_HOME}/conf/flink-conf.yaml 關于slot的配置如下&#xff1a; # The number of task slots that each TaskManager offers. Each slot runs one parallel pipeline. taskmanager.numberOfTas…

亞馬遜合規風控升級:詳情頁排查與多賬號運營安全構建

2025年亞馬遜掀起的大規模掃號行動&#xff0c;聚焦商品詳情頁合規性審查&#xff0c;標志著跨境電商合規監管進入嚴風控時代&#xff0c;此次行動以關鍵詞規范與定價誠信為核心&#xff0c;大量賣家因內容違規遭遇賬號停用&#xff0c;對于賣家而言&#xff0c;構建系統化的合…

FISCO-BCOS-Python 模板

基于Python-SDK的FISCO BCOS區塊鏈HelloWorld模板&#xff0c;提供了簡單的問候語設置和查詢功能。本項目采用現代Python開發實踐&#xff0c;包含完整的配置管理、測試框架和項目結構。 快速開始 倉庫地址&#xff1a;git clone https://gitee.com/atanycosts/python-fisco-te…

移動端(微信等)使用 vConsole調試console

本文介紹了一種在移動端真機上進行調試的方法——使用VConsole。通過簡單的安裝步驟和代碼配置&#xff0c;開發者可以在移動端直接查看console.log輸出&#xff0c;極大提升了調試效率。 摘要生成于 C知道 &#xff0c;由 DeepSeek-R1 滿血版支持&#xff0c; 前往體驗 >作…

云計算資源分配問題

這里寫目錄標題一、云計算資源的基本類型二、資源分配的目標三、資源分配的方式四、資源分配的技術與工具五、挑戰與優化方向六、實際應用場景舉例總結云計算資源分配是指在云計算環境中&#xff0c;根據用戶需求、應用程序性能要求以及系統整體效率&#xff0c;將計算、存儲、…

深度學習之第二課PyTorch與CUDA的安裝

目錄 簡介 一、PyTorch 與 CUDA 的核心作用 1.PyTorch 2.CUDA 二、CUDA的安裝 1.查看 2.下載安裝 3.檢查是否安裝成功 三、PyTorch的安裝 1.GPU版本安裝 2.CPU版本安裝 簡介 在深度學習的實踐旅程中&#xff0c;搭建穩定且高效的開發環境是一切實驗與項目的基礎&…

Ubuntu22.04 安裝和使用標注工具labelImg

文章目錄一、LabelImg 的安裝及配置1. 安裝2. 配置二、使用1. 基礎操作介紹2. 創建自定義標簽2.1 修改 predefined_classes.txt2.2 直接軟件界面新增3. 圖像標注3.1 重命名排序3.2 標注3.2 voc2yolo 格式轉換3.3 視頻轉圖片Yolo系列 —— Ubuntu 安裝和使用標注工具 labelImgYo…

Jenkins與Docker搭建CI/CD流水線實戰指南 (自動化測試與部署)

更多云服務器知識&#xff0c;盡在hostol.com你是否已經厭倦了那個“人肉”部署的重復循環&#xff1f;每一次 git push 之后&#xff0c;都像是一個莊嚴的儀式&#xff0c;你必須虔誠地打開SSH&#xff0c;小心翼翼地敲下一連串的 git pull, npm install, docker build, docke…

【數據可視化-100】使用 Pyecharts 繪制人口遷徙圖:步驟與數據組織形式

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

5G相對于4G網絡的優化對比

5G網絡作為新一代移動通信技術&#xff0c;相比4G實現了全方位的性能提升和架構優化。5G通過高速率、低時延和大連接三大核心特性&#xff0c;有效解決了4G網絡面臨的數據流量爆炸式增長和物聯網應用瓶頸問題 &#xff0c;同時引入了動態頻譜共享、網絡切片等創新技術&#xff…

AR智能巡檢:智慧工地的高效安全新引擎

在建筑行業,工地安全管理與施工效率的提升一直是核心議題。隨著增強現實(AR)技術的快速發展,AR智能巡檢系統正逐步成為智慧工地的“標配”,通過虛實結合、實時交互和智能分析,推動建筑行業邁入數字化、智能化的新階段。本文將從技術原理、應用場景、核心優勢及未來趨勢等…

TypeScript:枚舉類型

1. 什么是枚舉類型&#xff1f;枚舉&#xff08;Enum&#xff09;是TypeScript中一種特殊的數據類型&#xff0c;用于定義一組命名的常量值。它允許開發者用一個友好的名稱來代表數值或字符串&#xff0c;避免使用“魔法數字”或硬編碼值。基本語法&#xff1a;enum Direction …

Maven 編譯打包一個比較有趣的問題

前言最近做項目&#xff0c;發現一個比較有意思的問題&#xff0c;其實發現了問題的根源還是很好理解&#xff0c;但是如果突然看到會非常的難以理解。在Java項目中&#xff0c;明明包名錯誤了&#xff0c;居然可以正常編譯打包&#xff0c;IDEA報錯了&#xff0c;但是mvn命令正…

Leetcode貪心算法

題目&#xff1a;劃分字母區間 題號&#xff1a;763class Solution {public List<Integer> partitionLabels(String s) {List<Integer> list new LinkedList();int[] edge new int[27];char[] chars s.toCharArray();for(int i 0; i <chars.length;i){edge…

【密碼學基礎】加密消息語法 CMS:給數字信息裝個 “安全保險箱”

如果說數字世界是一座繁忙的城市&#xff0c;那么我們每天發送的郵件、合同、軟件安裝包就是穿梭在城市里的 “包裹”。有些包裹里裝著隱私&#xff08;比如銀行賬單&#xff09;&#xff0c;有些裝著重要承諾&#xff08;比如電子合同&#xff09;&#xff0c;還有些關系到設備…

leetcode算法刷題的第二十天

1.leetcode 39.組合總和 題目鏈接 這道題里面的數組里面的數字是可以重復使用的&#xff0c;那可能就會有人想&#xff0c;出現了0怎么辦&#xff0c;有這個想法的很好&#xff0c;但是題目要求數組里面的數字最小值為1&#xff0c;這就可以讓人放心了。但是有總和的限制&…

使用Spoon報錯Driver class ‘com.microsoft.sqlserver.jdbc.SQLServerDriver‘ could not be found解決方法

使用Spoon報錯Driver class ‘com.microsoft.sqlserver.jdbc.SQLServerDriver’ could not be found 產生原因 出現這個錯誤是因為Spoon無法找到用于連接MS SQL Server的JDBC驅動程序。該驅動程序是一個jar文件,通常需要手動下載并配置。 解決方案 下載JDBC驅動程序: 訪問 M…