.NET 8 集成 JWT Bearer Token

注意:這是一種非常簡單且不是最低限度安全的設置 JWT 的方法。

步驟 1——安裝軟件包

首先,您需要安裝一些 NuGet 包。

dotnet add package Microsoft.AspCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt

步驟 2——創建類

你需要創建一些類來處理登錄請求、注冊請求和授權響應。你還需要某種類型的用戶。

using System.ComponentModel.DataAnnotations;

namespace Auth;

public class LoginRequest
{
[Required]
[EmailAddress]
public string Email { get; set; }

? ? [Required]
public string Password { get; set; }
}

using System.ComponentModel.DataAnnotations;

namespace Auth;

public class RegistrationRequest
{
[Required]
public string UserID { get; set; }

? ? [Required]
public string Username { get; set; }

? ? [Required]
public string Firstname { get; set; }

? ? [Required]
public string Lastname { get; set; }

? ? [Required]
[EmailAddress]
public string Email { get; set; }

? ? [Required]
public string Password { get; set; }
}

namespace Auth;

public class AuthResponse
{
public string UserId { get; set; }
public string Username { get; set; }
public string Token { get; set; }
public string? ProfileImage { get; set; }
}

步驟 3——創建控制器

當我們創建了類之后,我們需要實現注冊用戶和登錄的邏輯。我將跳過創建用戶的邏輯,只在我的示例中使用我的服務,您需要自己做這件事。

[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegistrationRequest request)
{
var salt = GenerateSalt();
var saltedPassword = request.Password + salt;

? ? var user = new User
{
Firstname = request.Firstname,
Lastname = request.Lastname,
Email = request.Email,
Password = _passwordHasher.HashPassword(null, saltedPassword), ? ?// Null is because the user is not created yet, normally this is where the user object is.
Salt = salt,
Role = Enums.Role.USER
};

? ? await _userService.CreateUser(user);
var token = _tokenService.CreateToken(user);

? ? return Ok(new AuthResponse { Token = token });
}

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
User? user = await _userService.FindByEmailAsync(request.Email); ? ? ? ?

? ? if (user == null)
{
return Unauthorized("Invalid credentials 1");
}

? ? var saltedPassword = request.Password + user.Salt;

var result = _passwordHasher.VerifyHashedPassword(user, user.Password,saltedPassword);

? ? if (result != PasswordVerificationResult.Success)
{
return Unauthorized("Invalid credentials 2");
}

? ? // Generate token
var token = _tokenService.CreateToken(user);

? ? // Return the token
return Ok(new AuthResponse { Token = token });
}

步驟4 —創建令牌服務

現在我們需要創建一個生成 JWT 令牌的方法。在我們的令牌中,我們可以添加任意數量的索賠正如我們想要的那樣。這里需要注意的是,我們的 SecurityTokenDescriptor 必須具有與“Program.cs”中的授權設置相同的令牌驗證參數。我們稍后會再討論這一點。我在這里使用的名為“_configuration”的變量,正是通過“IConfiguration”依賴注入到我的控制器中的。

public string CreateToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.UserID),
new Claim(ClaimTypes.Role, user.Role.ToString()),
// Add more claims as needed
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Issuer = _configuration["Jwt:Issuer"], // Add this line
Audience = _configuration["Jwt:Audience"]?
};

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

步驟 5 — 設置 Swagger 配置

現在我們需要配置 Swagger,以便稍后測試我們的端點。這里需要注意的是,當我們在 Swagger 的授權輸入框中輸入令牌字符串時,需要依次輸入:Bearer,后跟一個空格,然后是令牌字符串。

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "Pappa′s API", Version = "v1" });

? ? // Define the OAuth2.0 scheme that's in use (i.e., Implicit Flow)
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});

? ? c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
});

步驟 6——設置授權

這里重要的是,我們的令牌驗證參數與我們在令牌服務中的“CreateToken”方法中添加的參數相同。

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
});

步驟 7——設置中間件

我們放置中間件的順序非常重要,所以不要弄錯順序。我們也指定 Swagger 僅在開發環境中有效。

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

步驟 8 — 設置應用程序設置

現在我們需要將 JWT 值添加到我們的“apptsettings.json”文件中,包括密鑰、頒發者和受眾。出于演示和開發目的,我僅使用這些簡單的值。但請注意,密鑰尤其不應以純文本形式存儲,為了安全起見,最好將所有值存儲在安全的地方,例如 Azure Secrets 或 GitHub Secrets。

"Jwt": {
"Key": "your_secret_key_here_your_secret_key_here",
"Issuer": "your_issuer",
"Audience": "your_audience"
}

步驟 9 — 在控制器中設置授權

現在是時候將我們的令牌集成到我們的某個 API 中了。為此,我們讓 .NET 處理編碼,就像我們在“Program.cs”文件中設置的那樣。我們還添加了“[Authroize]”和“Roles”,以實現基于角色的身份驗證。如果您想添加更多角色,只需在同一字符串中用逗號分隔它們即可。

[HttpGet("getuser")]
[Authorize(Roles = "USER")]
public async Task<ActionResult<User>> GetUser()
{
// Retrieve userId from the claims
var userIdClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;

Console.WriteLine("Claims received:");
foreach (var claim in User.Claims)
{
Console.WriteLine($"{claim.Type}: {claim.Value}");
}

? ? ? ? if(userIdClaim == null)
{
return Unauthorized("No user ID claim present in token.");
}

try
{
User? user = await _userService.GetUser(userIdClaim);
return Ok(user);
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}

關于.NET8集成JWT本文先介紹到這里了。

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

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

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

相關文章

模型匯總-數學建模

一、優化模型1.線性規劃線性規劃&#xff08;Linear Programming, LP&#xff09;是一種數學優化方法&#xff0c;用于在給定的線性約束條件下&#xff0c;找到線性目標函數的最大值或最小值。它是運籌學中最常用的方法之一。線性規劃的標準形式最大化問題標準形式&#xff1a;…

2025年09月計算機二級MySQL選擇題每日一練——第十二期

計算機二級中選擇題是非常重要的&#xff0c;本期是這個系列的最后一期了&#xff01; 答案及解析將在末尾公布&#xff01; 今日主題&#xff1a;綜合應用進階 1、設有如下創建表的語句&#xff1a; CREATE TABLE tb_test( ID INT NOT NULL PRIMARY KEY, sno CHAR(10) NOT …

計組(2)CPU與指令

一、總體認識CPU1、軟硬件角度CPU&#xff0c;全稱就是中央處理器。從硬件上來說&#xff0c;CPU是一個超大規模集成電路&#xff0c;通過電路實現加法、乘法乃至各種各樣的處理邏輯。從軟件來說&#xff0c;CPU就是一個執行各種計算機指令的邏輯機器。2、計算機指令所謂的計算…

用Java讓家政服務觸手可及

家政服務不僅僅包括日常保潔&#xff0c;隨著社會的發展&#xff0c;從日常保潔、衣物清潔到家電維修、月嫂保姆&#xff0c;家政服務的場景越發多元。用戶不僅追求服務的 “專業度”&#xff0c;更看重 “便捷性”—— 能否快速找到服務、預約服務、了解服務效果&#xff1f;上…

Python OpenCV圖像處理與深度學習:Python OpenCV特征檢測入門

特征檢測與描述&#xff1a;探索圖像中的關鍵點 學習目標 通過本課程&#xff0c;學員們將掌握特征檢測的基本概念&#xff0c;了解如何使用OpenCV庫中的SIFT和SURF算法進行特征點檢測和特征描述符的計算。實驗將通過理論講解與實踐操作相結合的方式&#xff0c;幫助學員深入理…

ECDH (橢圓曲線迪菲-赫爾曼密鑰交換)

文章目錄一、什么是ECDH&#xff1f;二、為什么需要 ECDH&#xff1f;要解決什么問題&#xff1f;三、原理與圖示四、核心比喻&#xff1a;混合顏料五、技術實現步驟1. 約定公共參數2. 生成密鑰對3. 交換公鑰4. 計算共享密鑰5. 密鑰派生六、注意事項七、安全性基礎八、優勢特點…

Spring Boot實戰:打造高效Web應用,從入門到精通

目錄一、Spring Boot 初相識二、搭建開發環境2.1 安裝 JDK2.2 安裝 IDE&#xff08;以 IntelliJ IDEA 為例&#xff09;2.3 初始化 Spring Boot 項目三、Spring Boot 基礎配置3.1 配置文件詳解&#xff08;application.properties 和 application.yml&#xff09;3.2 自定義配置…

2025網絡安全宣傳周知識競賽答題活動怎么做

網絡安全答題PK小程序可以結合競技性、趣味性和知識性&#xff0c;設計以下核心功能模塊&#xff0c;提升用戶參與度和學習效果&#xff1a;一、核心PK功能實時對戰匹配 隨機匹配在線用戶&#xff08;按段位/積分相近原則&#xff09; 好友定向PK&#xff08;支持分享邀請對戰&…

echo、seq、{}、date、bc命令

文章目錄echo、seq、{}、date、bc命令echo案例seq命令案例{}花括號列表擴展序列擴展嵌套擴展datebc(高精度計算器)echo、seq、{}、date、bc命令 echo echo命令是一個常用的Shell命令&#xff0c;用于在終端上輸出文本。它的基本語法如下&#xff1a; echo [option] [string]…

Vue2之Vuex

文章目錄 數據準備新建項目選擇模塊安裝vscode工具打開 刪除無用文件刪除src/assets文件下的所有內容刪除src/components文件下的所有內容修改src/app.vuevscode運行項目 一、 概述1.是什么2. 使用場景3.優勢4 Vuex流程圖5.注意&#xff1a; 二、需求: 多組件共享數據創建三個組…

2025具身智能賽道觀察:技術、產業與視頻基礎設施

引言 2025 年&#xff0c;具身智能&#xff08;Embodied Intelligence&#xff09;毫無疑問已經成為全球資本追逐的“風口賽道”。從人形機器人、無人配送&#xff0c;到低空經濟和智能駕駛&#xff0c;幾乎所有與物理世界深度結合的領域&#xff0c;都被納入具身智能的廣義范…

【商業銀行風控模型(python版本,實操合集,附帶anaconda安裝教程,持續更新)】

Anaconda&#xff08;Python工具&#xff09;安裝1.Mac中安裝Anaconda2.點擊“Free Download”下載后&#xff0c;點擊“Skip registration”&#xff0c;跳過注冊環節。 3.conda list4.安裝完成Anaconda基本操作命令 # 查看當前虛擬環境下的所有包 conda list # 查看某個特定的…

FPGA DDR 地址映射-黃金法則

FPGA 中 DDR 控制器的地址映射順序&#xff08;Address Mapping Order&#xff09; 是優化設計速度&#xff08;帶寬和效率&#xff09; 的關鍵。簡單來說&#xff0c;地址映射順序決定了線性地址如何映射到 DDR 芯片內部的物理結構&#xff08;Bank、Row、Column&#xff09;。…

網絡安全設備監控指標

網絡安全設備監控指標 近日看到一篇設備情況匯報&#xff0c;內容寫得有些欠缺&#xff0c;因此我特意問了一下AI&#xff0c;整理了一下思路。以下是監控需要關注的性能指標。權當拋磚引玉。根據指標可以做監控&#xff0c;也可以做調研指標。 業務承載能力 吞吐量&#xff08…

JSP程序設計之JSP指令

1、JSP指令概念與分類 &#xff08;1&#xff09;概念 JSP指令相當于在編譯期間的命令&#xff0c;用來設置與整個JSP頁面相關的屬性&#xff0c;它并不直接產生任何可見的輸出&#xff0c;用來設置全局變量、聲明類、要實現的方法和輸出內容的類型等。在JSP文件被解析為Java…

Generative Art with p5.js: Creating Beauty from Code

Are you ready to make something truly beautiful with p5.js? Forget about boring bar charts and sales data—let’s create art that moves, breathes, and responds to your touch. We’re going to explore generative art, where code becomes your paintbrush and a…

Wi-Fi技術——網絡安全

一、數據幀的安全 1、無線網絡安全的發展 理論上無線電波范圍內的任何一個站點都可以監聽并登錄無線網絡&#xff0c;所有發送或接收的數據&#xff0c;都有可能被截取&#xff0c;因此無線網絡安全十分重要。 原始802.11的安全策略為WEP&#xff0c;其存在根本性的漏洞&#x…

Java提供高效后端支撐,Vue呈現直觀交互界面,共同打造的MES管理系統,含完整可運行源碼,實現生產計劃、執行、追溯一站式管理,提升制造執行效率

前言在當今競爭激烈的制造業環境中&#xff0c;企業面臨著提高生產效率、降低成本、保證產品質量以及快速響應市場變化等多重挑戰。制造執行系統&#xff08;MES&#xff0c;Manufacturing Execution System&#xff09;作為連接企業上層計劃管理系統&#xff08;如ERP&#xf…

【macOS】垃圾箱中文件無法清理的常規方法

【macOS】垃圾箱中文件無法清理的方法如果外接 SSD 移動盤上的垃圾文件無法刪除&#xff0c; 可能是由于文件系統格式不兼容、文件被占用、權限不足等原因導致的&#xff0c; 以下是一些常見的解決方法&#xff1a;檢查移動硬盤文件系統格式&#xff1a;如果移動硬盤是 NTFS 格…

鴻蒙ArkTS 核心篇-15-條件渲染(組件)

目錄 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 預覽效果 總結 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 let num: number 20Entry Component struct Index {build() {Column() {if (num 1) {Text(文本 1)} …