当前位置: 首页 > news >正文

ASP.NET Core 中的 JWT 鉴权实现

在当今的软件开发中,安全性和用户认证是至关重要的方面。JSON Web Token(JWT)作为一种流行的身份验证机制,因其简洁性和无状态特性而被广泛应用于各种应用中,尤其是在 ASP.NET Core 项目里。本文将详细介绍如何在 ASP.NET Core 应用中实现 JWT 鉴权,确保应用能够安全地验证用户身份并授权访问特定资源。

一、安装必要的 NuGet 包

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

这个包提供了 JWT 身份验证所需的所有功能,包括对 JWT 令牌的解析和验证。

二、配置 JWT 身份验证

在应用的配置文件 appsettings.json 中添加 JWT 相关的配置信息。这些配置包括密钥、发行者、受众和令牌的有效期等:

{"JwtSettings": {"Secret": "YourSecretKeyYourSecretKeyYourSecretKeyYourSecretKey",     // 用于加密的密钥(应非常复杂)"Issuer": "YourAppName",       // 发行者"Audience": "YourAppUsers",    // 受众"ExpireMinutes": 120           // 令牌有效期}
}

在 Program.cs 文件中,需要配置 JWT 认证方案,以便 ASP.NET Core 知道如何处理 JWT 令牌:

var builder = WebApplication.CreateBuilder(args);var jwtSettings = builder.Configuration.GetSection("JwtSettings");builder.Services.AddAuthentication(options =>
{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,ValidateAudience = true,ValidateLifetime = true,ValidateIssuerSigningKey = true,ValidIssuer = jwtSettings["Issuer"],ValidAudience = jwtSettings["Audience"],IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Secret"])),ClockSkew = TimeSpan.Zero  // 默认的 5 分钟偏移时间};options.Events = new JwtBearerEvents
{ OnMessageReceived = context =>{var token = context.Request.Headers["Authorization"].ToString()?.Replace("Bearer ", "");if (!string.IsNullOrEmpty(token)){context.Token = token;}return Task.CompletedTask;},OnAuthenticationFailed = context =>{// 如果过期,把过期信息添加到头部if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)){context.Response.Headers.Append("Token-Expired", "true");}return Task.CompletedTask;} 
};
});var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();

配置了 JWT 身份验证的中间件,确保所有传入的请求都会被检查是否包含有效的 JWT 令牌。

JwtBearerEvents的订阅事件

    //  1. **OnMessageReceived**://   -触发时机:当接收到一个身份验证请求。//   -用途:用来处理接收到的原始身份验证消息,可以根据请求的具体情况来修改或取消身份验证过程。//2. * *OnTokenValidated * *://   -触发时机:在JWT被成功验证后触发。//   -用途:用来处理已验证的token,例如,可以在这里添加额外的日志记录或执行一些安全检查。//3. * *OnAuthenticationFailed * *://   -触发时机:当身份验证失败时触发。//   -用途:用来处理身份验证失败的情况,例如,记录失败原因、执行额外的错误处理逻辑等。//4. * *OnChallenge * *://   -触发时机:当需要向客户端发出一个挑战(例如,要求客户端提供凭据)时触发。//   -用途:自定义挑战的响应,例如,修改返回给客户端的`401 Unauthorized`响应。//5. * *OnForbidden * *://   -触发时机:当授权失败时触发(即用户已通过身份验证,但没有足够的权限访问特定资源)。//   -用途:自定义处理禁止访问的情况,例如,返回一个自定义的错误消息或执行其他逻辑。

三、生成 JWT Token

为了使用户能够登录并获取 JWT 令牌,需要创建一个控制器或服务来处理登录请求并生成 JWT 令牌。以下是一个简单的登录 API 示例:

using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;[ApiController]
[Route("api/[controller]")]
publicclassAuthController : ControllerBase
{privatereadonly IConfiguration _configuration;public AuthController(IConfiguration configuration){_configuration = configuration;}[HttpPost("login")]public IActionResult Login([FromBody] LoginRequest loginRequest){// 假设已经验证了用户名和密码if (loginRequest.Username == "admin" && loginRequest.Password == "password"){var token = GenerateJwtToken(loginRequest.Username);return Ok(new { token });}return Unauthorized();}private string GenerateJwtToken(string username){var jwtSettings = _configuration.GetSection("JwtSettings");var claims = new[]{new Claim(JwtRegisteredClaimNames.Sub, username),new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())//添加更多的标识};var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Secret"]));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var token = new JwtSecurityToken(issuer: jwtSettings["Issuer"],audience: jwtSettings["Audience"],claims: claims,expires: DateTime.Now.AddMinutes(double.Parse(jwtSettings["ExpireMinutes"])),signingCredentials: creds);returnnew JwtSecurityTokenHandler().WriteToken(token);}
}publicclassLoginRequest
{publicstring Username { get; set; }publicstring Password { get; set; }
}

四、保护 API 路由

一旦有了 JWT 令牌生成机制,接下来需要保护 API 路由,确保只有携带有效 JWT 令牌的请求可以访问受保护的资源。

可以通过在控制器或操作方法上使用 [Authorize] 特性来实现:

[AllowAnonymous]可跳过授权

[ApiController]
[Route("[controller]")]
[Authorize]
publicclassWeatherForecastController : ControllerBase
{[Authorize][HttpGet(Name = "GetWeatherForecast")]public IEnumerable<WeatherForecast> Get(){return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),TemperatureC = Random.Shared.Next(-20, 55),Summary = Summaries[Random.Shared.Next(Summaries.Length)]}).ToArray();}
}

五、客户端请求

客户端在请求受保护的 API 时,必须在请求头中添加 Authorization 字段,格式为 Bearer <token>

GET /api/protected/data HTTP/1.1
Host: yourdomain.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

这样,服务器就能通过 JWT 中间件验证令牌的有效性,并允许或拒绝请求。

六、扩展:Swagger集成,传递验证

需要使用包Swashbuckle.AspNetCore

builder.Services.AddSwaggerGen(options => options.SwaggerTokenConfigure());
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}

SwaggerConfiguration将token保存到swagger并传递到后台

public staticclassSwaggerConfiguration
{public static void SwaggerTokenConfigure(this SwaggerGenOptions options){options.SwaggerDoc("v1", new OpenApiInfo{Title = "JWT Auth API",Version = "v1",Description = "A sample API for JWT Authentication"});options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme{Description = "JWT Authorization header using the Bearer scheme.",Name = "Authorization",In = ParameterLocation.Header,Type = SecuritySchemeType.Http,Scheme = "Bearer",BearerFormat = "JWT"});options.AddSecurityRequirement(new OpenApiSecurityRequirement{{new OpenApiSecurityScheme{Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme,Id = "Bearer"}},Array.Empty<string>()}});}
}

有关swagger更多的详细配置,请参考
https://mp.weixin.qq.com/s/Xke2EyUHuxR_RdHbSXP5Ew

分组:https://mp.weixin.qq.com/s/Ut9leANrq4pJMgOQFmVkqg

七、扩展:获取身份验证信息

老规矩,先注册

builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddTransient<IAppUser, AppUser>();

存放用户信息的接口和实现类

    public interfaceIAppUser{string Username { get; }string HeaderToken { get; }}publicclassAppUser : IAppUser{privatereadonly HttpContext _httpContext;public AppUser(IHttpContextAccessor httpContextAccessor){_httpContext = httpContextAccessor?.HttpContext;}publicstring Username { get => _httpContext?.User.Claims.FirstOrDefault(s => s.Type == "Username")?.Value.ToString()??""; }publicstring HeaderToken{get{if (_httpContext.Request.Headers.ContainsKey("Authorization")){return _httpContext?.Request.Headers["Authorization"].ToString().Replace("Bearer ", "").Trim();}returnstring.Empty;}}}

直接使用

 private readonly IAppUser _appUser ;public AuthController(IConfiguration configuration, IAppUser appUser){_configuration = configuration;_appUser=appUser;}[HttpGet]public IActionResult Getuserinfo(){return Ok(new { _appUser.Username, _appUser.HeaderToken });}

可以成功获取到用户存放的token信息,不过现在还有一个弊端,就是每次都需要构造注入才可以过去用户信息,是比较麻烦的,其实我们可以通过封装一下,将AppUser存放到App全局配置里面直接静态获取,这样在需要获取用户信息的时候,就不需要每次都构造注入了
等后面有机会出优化和封装教程,或者直接参考:https://gitee.com/Pridejoy/MalusAdmin

八、可选:角色授权

如果应用需要基于角色进行授权,可以在生成 JWT 令牌时添加角色信息:

private string GenerateJwtToken(string username)
{var claims = new[]{new Claim(JwtRegisteredClaimNames.Sub, username),new Claim(ClaimTypes.Role, "Admin"),  // 添加角色new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())};// 剩余代码与前面一致
}

然后,可以使用 [Authorize(Roles = "Admin")] 特性来限定只有特定角色的用户才能访问:

[Authorize(Roles = "Admin")]
[HttpGet("admin-data")]
public IActionResult GetAdminData()
{return Ok(new { message = "This is admin data" });
}

总结

通过以上操作,就可以在 ASP.NET Core 应用中实现 JWT 鉴权,确保你的应用能够安全地验证用户身份并授权访问特定资源。JWT 的无状态特性和灵活性使其成为现代 Web 应用中身份验证的理想选择。

相关文章:

ASP.NET Core 中的 JWT 鉴权实现

在当今的软件开发中&#xff0c;安全性和用户认证是至关重要的方面。JSON Web Token&#xff08;JWT&#xff09;作为一种流行的身份验证机制&#xff0c;因其简洁性和无状态特性而被广泛应用于各种应用中&#xff0c;尤其是在 ASP.NET Core 项目里。本文将详细介绍如何在 ASP.…...

PyTorch基本功能与实现代码

PyTorch是一个开源的深度学习框架&#xff0c;提供了丰富的函数和工具&#xff0c;以下为其主要功能的归纳&#xff1a; 核心数据结构&#xff1a; • 张量&#xff08;Tensor&#xff09;&#xff1a;类似于Numpy的ndarray&#xff0c;是PyTorch中基本的数据结构&#xff0c…...

SparkSQL数据模型综合实践

文章目录 1. 实战概述2. 实战步骤2.1 创建数据集2.2 创建数据模型对象2.2.1 创建常量2.2.2 创建加载数据方法2.2.3 创建过滤年龄方法2.2.4 创建平均薪水方法2.2.5 创建主方法2.2.6 查看完整代码 2.3 运行程序&#xff0c;查看结果 3. 实战小结 1. 实战概述 在本次实战中&#…...

3 查找重复的电子邮箱(having与where区别,distinct去重使用)

3 查找重复的电子邮箱&#xff08;having与where区别&#xff0c;distinct去重使用&#xff09; 表: Person ---------------------- | Column Name | Type | ---------------------- | id | int | | email | varchar | ---------------------- id 是该…...

uniapp——App 监听下载文件状态,打开文件(三)

5 实现下载文件并打开 这里演示&#xff0c;导出Excel 表格 文章目录 5 实现下载文件并打开DEMO监听下载进度效果图为什么 totalSize 一直为0&#xff1f; 相关Api&#xff1a; downloader DEMO 提示&#xff1a; 请求方式支持&#xff1a;GET、POST&#xff1b;POST 方式需要…...

循环队列(C语言)

从今天开始我会开启一个专栏leetcode每日一题&#xff0c;大家互相交流代码经验&#xff0c;也当作我每天练习的自我回顾。第一天的内容是leetcode622.设计循环队列。 一、题目详细 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#…...

数据可视化:让数据讲故事的艺术

目录 1 前言2 数据可视化的基本概念2.1 可视化的核心目标2.2 传统可视化手段 3 数据可视化在知识图谱中的应用3.1 知识图谱的可视化需求3.2 知识图谱的可视化方法 4 数据可视化叙事&#xff1a;让数据讲故事4.1 叙事可视化的关键要素4.2 数据可视化叙事的实现方法 5 数据可视化…...

雷电9最新版安装Magisk+LSPosd(新手速通)

大家好啊&#xff01;我是NiJiMingCheng 我的博客&#xff1a;NiJiMingCheng 在安卓系统的定制与拓展过程中&#xff0c;获取 ROOT 权限以及安装各类框架是进阶玩家常用的操作&#xff0c;这可以帮助我们实现更多系统层面的个性化功能。今天&#xff0c;我将为大家详细介绍如何…...

Ubuntu 24.04 LTS 开启 SMB 服务,并通过 windows 访问

Ubuntu 24.04 LTS 背景资料 Ubuntu服务器折腾集Ubuntu linux 文件权限Ubuntu 空闲硬盘挂载到 文件管理器的 other locations Ubuntu开启samba和window共享文件 Ubuntu 配置 SMB 服务 安装 Samba 确保 Samba 已安装。如果未安装&#xff0c;运行以下命令进行安装&#xff…...

使用Websocket进行前后端实时通信

1、引入jar&#xff0c;spring-websocket-starter <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency> 2、配置websocket config import org.springframe…...

vue2使用flv.js在浏览器打开flv格式视频

组件地址&#xff1a;GitHub - bilibili/flv.js: HTML5 FLV Player flv.js 仅支持 H.264 和 AAC/MP3 编码的 FLV 文件。如果视频文件使用了其他编码格式就打不开。 flv.vue <template><div><el-dialog :visible.sync"innerVisibleFlv" :close-on-pre…...

OpenCV相机标定与3D重建(61)处理未校准的立体图像对函数stereoRectifyUncalibrated()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 为未校准的立体相机计算一个校正变换。 cv::stereoRectifyUncalibrated 是 OpenCV 库中的一个函数&#xff0c;用于处理未校准的立体图像对。该函…...

[cg] glProgramBinary

参考&#xff1a; glProgramBinary - OpenGL 4 Reference Pages opengl 通过gpu编译好的 shader 可以存储到二进制文件中&#xff0c;第二次使用的时候直接加载二进制文件即可&#xff0c; glProgramBinary用于加载shader的二进制数据 实列代码如下&#xff1a; // 假设已经…...

LeetCode hot 力扣热题100 二叉树的最大深度

class Solution { public:int maxDepth(TreeNode* root) {if (root nullptr) {return 0;}int l_depth maxDepth(root->left);int r_depth maxDepth(root->right);return max(l_depth, r_depth) 1;} }; 代码作用 该函数通过递归计算二叉树的最大深度&#xff08;从根节…...

速通Docker === 网络

目录 Docker网络详解 容器之间直接通信的弊端 &#xff08;一&#xff09;启动容器 &#xff08;二&#xff09;进入容器并发起请求 &#xff08;三&#xff09;请求流程 &#xff08;四&#xff09; 弊端分析 一、Docker网络基础 &#xff08;一&#xff09;容器IP分配…...

【MySQL — 数据库基础】深入解析MySQL常用数据类型

常用数据类型 创建完数据库之后&#xff0c;就要在数据库中创建表&#xff0c;表中存储的数据记录&#xff0c;一条记录由不同的列组成&#xff0c;每条列都需要自己的类型&#xff1b;并且表中的多个行对应的列的数据类型&#xff0c;都必须是相同的&#xff1b; 那么每个…...

Linux高级--3.3.1 C++ spdlog 开源异步日志方案

一、基本介绍 spdlog 是由 Gustav S. 在 2015 年开发的一个高性能 C 日志库。开发这个库的主要目的是为了提供一个非常快速、轻量、易于使用的日志工具&#xff0c;特别适合需要高性能、低延迟日志记录的 C 应用程序。&#xff08;由于源码现在比较难下载&#xff0c;我把压缩…...

电梯系统的UML文档05

Dispatcher 不控制实际的电梯组件&#xff0c;但它在软件系统中是重要的。每一个电梯有一个ispatcher&#xff0c;主要功能是计算电梯的移动方向、移动目的地以及保持门的打开时间。它和系统中除灯控制器以外的几乎所有控制对象交互。 安全装置也是一个环境对象&#xff0c;它…...

如何使 LLaMA-Factory 支持 google/gemma-2-2b-jpn-it 的微调

如何使 LLaMA-Factory 支持 google/gemma-2-2b-jpn-it 的微调 追加&#xff0c; "Gemma-2-2B-JPN-Instruct": {DownloadSource.DEFAULT: "google/gemma-2-2b-jpn-it",},修改 constants.py&#xff0c; vi ./src/llamafactory/extras/constants.py---"…...

MySQL中日期和时间戳的转换:字符到DATE和TIMESTAMP的相互转换

在MySQL中&#xff0c;经常需要在 DATE、TIMESTAMP 和字符串之间进行相互转换。以下是一些常见的转换方法&#xff1a; 1. 字符串到日期/时间类型 字符串转 DATE: 使用 STR_TO_DATE() 函数将字符串转换为 DATE 类型。你需要提供字符串的格式。 SELECT STR_TO_DATE(2024-08-24,…...

RT-Thread实时操作系统入门与实践指南

1. RT-Thread 入门指南&#xff1a;从零开始掌握实时操作系统 RT-Thread 作为一款国产开源实时操作系统&#xff08;RTOS&#xff09;&#xff0c;近年来在物联网、智能硬件等领域获得了广泛应用。对于嵌入式开发者而言&#xff0c;掌握 RT-Thread 不仅能提升开发效率&#xff…...

GCViewer扩展开发终极指南:自定义数据读取器与导出格式的完整教程

GCViewer扩展开发终极指南&#xff1a;自定义数据读取器与导出格式的完整教程 【免费下载链接】GCViewer Fork of tagtraum industries GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Suns / Oracles java 1.6 garbage collector logs (inclu…...

如何永久保存微信聊天记录:WeChatMsg本地数据备份完整指南

如何永久保存微信聊天记录&#xff1a;WeChatMsg本地数据备份完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/W…...

2026最全国内外电商API接口的数据列表与采集

电商数据采集 API 主要分为 官方开放平台 API&#xff08;合规、稳定&#xff09;和 第三方聚合 API&#xff08;多平台统一、接入快&#xff09;。下面按 国内主流平台&#xff08;淘宝 / 天猫、京东、1688、拼多多&#xff09; 跨境平台&#xff08;亚马逊、速卖通、Shopee&a…...

向上生长,智赢未来 | 优美优品2026经销商大会圆满

引言2026年3月18日&#xff0c;一个看似平常的日子。但对优美优品而言&#xff0c;这是值得被标记的一天。全国各地的经销商伙伴跨越山海&#xff0c;奔赴而来。他们不是来参加一场普通的年度会议&#xff0c;而是来寻找一个答案。当房地产下行、消费信心不足、行业加速洗牌&am…...

Agentic AI 深度解析:当人工智能学会“动手”

从“回答问题”到“完成任务”&#xff0c;Agentic AI 正在重新定义人工智能的边界。它不是“更大的聊天机器人”&#xff0c;而是能够自主规划、调用工具、执行多步任务并持续迭代的智能体系统。一、什么是 Agentic AI&#xff1f;——重新定义“智能” Agentic AI&#xff08…...

突破语言壁垒:FanControl本地化引擎深度配置指南

突破语言壁垒&#xff1a;FanControl本地化引擎深度配置指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/FanC…...

VCF 私有 AI 服务(PAIS)自签名 TLS 证书配置避坑指南

在实验室或概念验证环境中&#xff0c;自签名 TLS 证书是 VCF 私有 AI 服务(PAIS)部署的常用选择&#xff0c;但常因底层库验证机制差异引发各类报错。本文针对 PAIS 部署中两类高频证书问题 ——API 容器启动失败与 Harbor 模型推送报错&#xff0c;拆解报错根源&#xff0c;提…...

LAYONTHEGROUND筛

一、什么是requests&#xff1f; requests 是一个用于发送HTTP请求的 Python 库。 它可以帮助你&#xff1a; 轻松发送GET、POST、PUT、DELETE等请求 处理Cookie、会话等复杂性 自动解压缩内容 处理国际化域名和URL 二、应用场景 requests 广泛应用于以下实际场景&#xff1a; …...

PHP 8.9 JIT调试稀缺资源包首发:含自研jit-trace-analyzer工具链、12个真实微服务JIT崩溃core dump样本(限前500名下载)

第一章&#xff1a;PHP 8.9 JIT调试稀缺资源包发布说明 PHP 社区正式发布首个面向 PHP 8.9&#xff08;开发代号“Vesuvius”&#xff09;的 JIT 调试资源包&#xff08;JIT Debug Resource Pack, JD-RP v0.1.0&#xff09;&#xff0c;专为深度分析 OPCache JIT 编译行为、寄存…...