在 .NET 8/9 中使用 AppUser 进行 JWT 令牌身份验证
文章目录
- 一、引言
- 二、什么是 JSON Web 令牌?
- 三、什么是 JSON Web 令牌结构?
- 四、设置 JWT 令牌身份验证
- 4.1 创建新的 .NET 8 Web API 项目
- 4.2 安装所需的 NuGet 软件包
- 4.3 创建 JWT 配置模型
- 4.4 将 JWT 配置添加到您的 appsettings.json 中
- 4.5 为 Configuration 配置 DIProgram.cs
- 4.6 配置 JWT 身份验证扩展
- 4.7 在 Program.cs 配置
- 4.8 创建 Token 生成服务
- 4.9 注册 Token Service
- 4.10 添加登录端点或控制器
- 4.11 新增 SwaggerConfiguration(方便测试)
- 4.12 添加 AppUser
- 4.13 为所有 Controller 或端点添加 Authorize 属性
- 五、测试
一、引言
本文介绍了在 .NET 8 Web
应用程序中通过 AppUser
类实现 JWT
令牌身份验证的过程。JWT
身份验证是保护 API
的标准方法之一,它允许无状态身份验证,因为签名令牌是在客户端和服务器之间传递的。
二、什么是 JSON Web 令牌?
JSON Web 令牌(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于将信息作为 JSON
对象在各方之间安全地传输。此信息是经过数字签名的,因此可以验证和信任。可以使用密钥(使用 HMAC
算法)或使用 RSA
或 ECDSA
的公钥/私钥对对 JWT
进行签名。
三、什么是 JSON Web 令牌结构?
在其紧凑形式中,JSON Web
令牌由三个部分组成,由点(.
)分隔,它们是:
- 页眉
- 有效载荷
- 签名
因此,JWT
通常如下所示:xxxxx.yyyyy.zzzzz
四、设置 JWT 令牌身份验证
4.1 创建新的 .NET 8 Web API 项目
dotnet new webapi -n JwtAuthApp
4.2 安装所需的 NuGet 软件包
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Tokens
4.3 创建 JWT 配置模型
using System.Globalization;
namespace JwtAuthApp.JWT
{public class JwtConfiguration{public string Issuer { get; } = string.Empty;public string Secret { get; } = string.Empty;public string Audience { get; } = string.Empty;public int ExpireDays { get; }public JwtConfiguration(IConfiguration configuration){var section = configuration.GetSection("JWT");Issuer = section[nameof(Issuer)];Secret = section[nameof(Secret)];Audience = section[nameof(Audience)];ExpireDays = Convert.ToInt32(section[nameof(ExpireDays)], CultureInfo.InvariantCulture);}}
}
4.4 将 JWT 配置添加到您的 appsettings.json 中
{"Jwt": {"Issuer": "JwtAuthApp","Audience": "https://localhost:7031/","Secret": "70FC177F-3667-453D-9DA1-AF223DF6C014","ExpireDays": 30}
}
4.5 为 Configuration 配置 DIProgram.cs
builder.Services.AddTransient<JwtConfiguration>();
4.6 配置 JWT 身份验证扩展
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;namespace JwtAuthApp.JWT
{public static class JwtAuthBuilderExtensions{public static AuthenticationBuilder AddJwtAuthentication(this IServiceCollection services, IConfiguration configuration){var jwtConfiguration = new JwtConfiguration(configuration);services.AddAuthorization();return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{options.SaveToken = true;options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,ValidateAudience = true,ValidateLifetime = true,ValidateIssuerSigningKey = true,ValidIssuer = jwtConfiguration.Issuer,ValidAudience = jwtConfiguration.Audience,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfiguration.Secret)),ClockSkew = TimeSpan.Zero};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;}};});}}
}
4.7 在 Program.cs 配置
var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddJwtAuthentication(builder.Configuration);var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();app.MapControllers();app.Run();
4.8 创建 Token 生成服务
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;namespace JwtAuthApp.JWT
{public class TokenService{private readonly JwtConfiguration _config;public TokenService(JwtConfiguration config){_config = config;}public string GenerateToken(string userId, string email){var claims = new[]{new Claim(JwtRegisteredClaimNames.Sub, userId),new Claim(JwtRegisteredClaimNames.Email, email)};var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.Secret));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var token = new JwtSecurityToken(issuer: _config.Issuer,audience: _config.Audience,claims: claims,expires: DateTime.Now.AddDays(_config.ExpireDays),signingCredentials: creds);return new JwtSecurityTokenHandler().WriteToken(token);}}
}
4.9 注册 Token Service
builder.Services.AddTransient<TokenService>();
4.10 添加登录端点或控制器
app.MapPost("/login", [FromBody] LoginRequest request, TokenService tokenService)
{if (request.Username == "admin" && request.Password == "admin"){var userId = "123456"; // 从数据库获取用户 IDvar email = "admin@example.com"; // 从数据库获取用户邮箱var token = tokenService.GenerateToken(userId, email);return Results.Ok(new { token });}return Results.Unauthorized();
})
.WithName("Login")
.RequireAuthorization();
4.11 新增 SwaggerConfiguration(方便测试)
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;namespace JwtAuthApp.JWT
{public static class SwaggerConfiguration{public static void Configure(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>()}});}}
}
4.12 添加 AppUser
public class AppUser : ClaimsPrincipal{ public AppUser(IHttpContextAccessor contextAccessor) : base(contextAccessor.HttpContext.User) { }public string UserID => FindFirst(CustomerConst.UserID)?.Value ?? "";public string OpenId => FindFirst(CustomerConst.OpenId)?.Value ?? ""; }builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<AppUser>();
4.13 为所有 Controller 或端点添加 Authorize 属性
app.MapGet("/weatherforecast", [Authorize] () =>
{// ...
})
.WithName("GetWeatherForecast")
.WithOpenApi();app.MapGet("/user", [Authorize] (AppUser user) =>
{return Results.Ok(new { user.Email });
})
.WithName("GetUserEmail")
.WithOpenApi();
五、测试
- 所有端点
- 获取天气预报在登录前收到错误 401 (未授权)
- 登录返回的
jwt
令牌 - 在
Swagger Auth
中使用jwt
令牌 - 获取天气预报返回结果
- 获取用户电子邮件 返回用户电子邮件
相关文章:

在 .NET 8/9 中使用 AppUser 进行 JWT 令牌身份验证
文章目录 一、引言二、什么是 JSON Web 令牌?三、什么是 JSON Web 令牌结构?四、设置 JWT 令牌身份验证4.1 创建新的 .NET 8 Web API 项目4.2 安装所需的 NuGet 软件包4.3 创建 JWT 配置模型4.4 将 JWT 配置添加到您的 appsettings.json 中4.5 为 Config…...
基于python实现机器学习的心脏病预测系统
以下是一个基于 Python 实现的简单心脏病预测系统代码示例,我们将使用 Scikit - learn 库中的机器学习算法(这里以逻辑回归为例),并使用公开的心脏病数据集。 步骤: 数据加载与预处理:加载心脏病数据集&a…...
使用 NVM 随意切换 Node.js 版本
安装nvm https://github.com/coreybutler/nvm-windows/releases nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)-CSDN博客 验证 NVM 是否安装成功-查看版本 nvm --version安装指定版本的 Node.js nvm i…...

【Prometheus】prometheus结合pushgateway实现脚本运行状态监控
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...
SpringBoot 项目配置动态数据源
目录 一、前言二、操作1、引入依赖2、配置默认数据库 13、定义数据源实体和 Repository4、定义动态数据源5、配置数据源6、定义切换数据源注解7、定义切面类8、使用注解切换数据源 一、前言 通过切面注解方式根据不同业务动态切换数据库 二、操作 1、引入依赖 <dependen…...

CSS基本选择器
1. 通配选择器 作用:可以选中所有的 HTML 元素。 语法: * { 属性名: 属性值; } 举例: <!DOCTYPE html> <html lang"zh-cn"> <head><meta charset"UTF-8"><meta name"viewport" …...

idea-代码补全快捷键
文章目录 前言idea-代码补全快捷键1. 基本补全2. 类型匹配补全3. 后缀补全4. 代码补全 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 而且听说点赞的人每天的运气都不会太差,…...

基于SpringBoot+vue粮油商城小程序系统
粮油商城小程序为用户提供方便快捷的在线购物体验,包括大米、面粉、食用油、调味品等各种粮油产品的选购,用户可以浏览商品详情、对比价格、下单支付等操作。同时,商城还提供优惠活动、积分兑换等福利,让用户享受到更多实惠和便利…...

挪车小程序挪车二维码php+uniapp
一款基于FastAdminThinkPHP开发的匿名通知车主挪车微信小程序,采用匿名通话的方式,用户只能在有效期内拨打车主电话,过期失效,从而保护车主和用户隐私。提供微信小程序端和服务端源码,支持私有化部署。 更新日志 V1.0…...

企业内部知识库:安全协作打造企业智慧运营基石
内容概要 作为企业智慧运营的核心载体,企业内部知识库通过结构化的信息聚合与动态化的知识流动,为组织提供了从数据沉淀到价值转化的系统性框架。其底层架构以权限管理为核心,依托数据加密技术构建多层级访问控制机制,确保敏感信…...

网络安全推荐的视频教程 网络安全系列
第一章 网络安全概述 1.2.1 网络安全概念P4 网络安全是指网络系统的硬件、软件及其系统中的数据受到保护,不因偶然的或恶意的原因而遭到破坏、更改、泄露,系统连续可靠正常地运行,网络服务不中断。 1.2.3 网络安全的种类P5 (1…...

麒麟管家全新升级,运维问题“一键修复”
麒麟管家是openKylin社区SystemManager SIG开发的一款面向社区用户,能倾听用户烦恼和诉求,也能提供便利途径、解决用户问题的系统管理类应用,可以为用户提供问题反馈、系统垃圾清理、电脑故障排查、硬件设备管理及系统小工具等一站式服务&…...
MVCC(多版本并发控制)机制讲解
MVCC(Multi-Version Concurrency Control,多版本并发控制)这是一个在数据库管理系统中非常重要的技术,尤其是在处理并发事务时。别担心,我会用简单易懂的方式来讲解,让你轻松掌握它的原理和作用。 1. 什么是…...

React 与 Vue 对比指南 - 上
React 与 Vue 对比指南 - 上 本文将展示如何在 React 和 Vue 中实现常见功能,从基础渲染到高级状态管理 Hello 分别使用 react 和 vue 写一个 Hello World! react export default () > {return <div>Hello World!</div>; }vue <…...

开源协议深度解析:理解MIT、GPL、Apache等常见许可证
目录 前言1. MIT协议:自由而宽松的开源许可1.1 MIT协议的主要特点1.2 MIT协议的适用场景 2. GPL协议:自由软件的捍卫者2.1 GPL协议的核心理念2.2 GPL协议的适用场景 3. Apache License 2.0:开源与专利保护的平衡3.1 Apache License 2.0的主要…...

通用评估系统(五)- 前端部分总体说明
通用评估系统(五)- 前端部分总体说明 相关链接 Gitee地址通用评估系统(一)- 介绍通用评估系统(二)- 原型设计通用评估系统(三)- 前端部分通用评估系统(四)-…...

STM32GPIO
目录 GPIO基本结构GPIO位结构输入部分输出部分 输出模式GPIO模式浮空/上拉/下拉模拟输入开漏和推挽复用开漏/复用推挽 GPIO基本结构 GPIO是挂载在APB2总线上的外设。GPIO结构中的寄存器分为输入寄存器和输出寄存器,APB2总线通过输出寄存器向引脚发送数据,…...
MyBatis拦截器终极指南:从原理到企业级实战
在本篇文章中,我们将深入了解如何编写一个 MyBatis 拦截器,并通过一个示例来展示如何在执行数据库操作(如插入或更新)时,自动填充某些字段(例如 createdBy 和 updatedBy)信息。本文将详细讲解拦…...

SpringBoot启动失败之application.yml缩进没写好
修改前: spring前面空格了 报错输出:Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the follow…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter17-事件
十七、事件 事件 JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻。可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件。在传统软件工程领域,这个模型叫“观察者模式”ÿ…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...