在 .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 算法)或使用 RSAECDSA 的公钥/私钥对对 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 令牌
  • 获取天气预报返回结果
  • 获取用户电子邮件 返回用户电子邮件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22693.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

问卷数据分析|SPSS实操之相关分析

皮尔逊还是斯皮尔曼的选取主要看数据的分布 当数据满足正态分布且具有线性关系时&#xff0c;用皮尔逊相关系数 当有一个不满住时&#xff0c;用斯皮尔曼相关系数 1. 选择分析--相关--双变量 2. 将Z1-Y2加入到变量中&#xff0c;选择皮尔逊 3. 此处为结果&#xff0c;可看我案…

自动化办公|xlwings生成图表

在日常的数据分析和报告生成中&#xff0c;Excel图表是一个非常重要的工具。它能够帮助我们直观地展示数据&#xff0c;发现数据中的规律和趋势。然而&#xff0c;手动创建和调整图表往往耗时且容易出错。幸运的是&#xff0c;借助Python的xlwings库&#xff0c;我们可以自动化…

Javascript使用Sodium库实现 aead_xchacha20poly1305_ietf加密解密,以及与后端的密文交互

Node.js环境安装 sodium-native (其他库可能会出现加密解密失败&#xff0c;如果要使用不一样的库&#xff0c;请自行验证) npm install sodium-native 示例代码&#xff0c;使用的是 sodium-native v4.3.2 (其他版本可能会有变化&#xff0c;如果要使用&#xff0c;请自行验…

【Linux】匿名管道的应用场景-----管道进程池

目录 一、池化技术 二、简易进程池的实现&#xff1a; Makefile task.h task.cpp Initchannel函数&#xff1a; 创建任务&#xff1a; 控制子进程&#xff1a; 子进程执行任务&#xff1a; 清理收尾&#xff1a; 三、全部代码&#xff1a; 前言&#xff1a; 对于管…

使用LangChain构建第一个ReAct Agent

使用LangChain构建第一个ReAct Agent 准备环境 使用Anaconda 安装python 3.10 安装langchain、langchain_openai、langchain_community &#xff08;安装命令 pip install XXX&#xff09; 申请DeepSeek API&#xff1a;https://platform.deepseek.com/api_keys&#xff08;也…

多人协同创作gitea

多人协同创作gitea 在多台设备上协同使用Gitea&#xff0c;主要是通过网络访问Gitea服务器上的仓库来进行代码管理和协作。以下是一些关键步骤和建议&#xff0c;帮助你在多台设备上高效地使用Gitea进行协作&#xff1a; 1. 确保Gitea服务可访问 首先&#xff0c;你需要确保…

【个人开源】——从零开始在高通手机上部署sd(二)

代码&#xff1a;https://github.com/chenjun2hao/qualcomm.ai 推理耗时统计 单位/ms 硬件qnncpu_clipqnncpu_unetqnncpu_vaehtp_cliphtp_unethtp_vae骁龙8 gen124716.994133440.39723.215411.097696.327 1. 下载依赖 下载opencv_x64.tar,提取码: rrbp下载opencv_aarch64.t…

SpringCloud系列教程:微服务的未来(二十五)-基于注解的声明队列交换机、消息转换器、业务改造

前言 在现代分布式系统中&#xff0c;消息队列是实现服务解耦和异步处理的关键组件。Spring框架提供了强大的支持&#xff0c;使得与消息队列&#xff08;如RabbitMQ、Kafka等&#xff09;的集成变得更加便捷和灵活。本文将深入探讨如何利用Spring的注解驱动方式来配置和管理队…

学习经验分享【39】YOLOv12——2025 年 2 月 19 日发布的以注意力为核心的实时目标检测器

YOLO算法更新速度很快&#xff0c;已经出到V12版本&#xff0c;后续大家有想发论文或者搞项目可更新自己的baseline了。 代码&#xff1a;GitHub - sunsmarterjie/yolov12: YOLOv12: Attention-Centric Real-Time Object Detectors 摘要&#xff1a;长期以来&#xff0c;增强 …

Pytorch实现之特征损失与残差结构稳定GAN训练,并训练自己的数据集

简介 简介:生成器和鉴别器分别采用了4个新颖设计的残差结构实现,同时在损失中结合了鉴别器层的特征损失来提高模型性能。 论文题目:Image Generation by Residual Block Based Generative Adversarial Networks(基于残留块的生成对抗网络产生图像) 会议:2022 IEEE Int…

后“智驾平权”时代,谁为安全冗余和体验升级“买单”

线控底盘&#xff0c;正在成为新势力争夺下一个技术普及红利的新赛点。 尤其是进入2025年&#xff0c;比亚迪、长安等一线传统自主品牌率先开启高阶智驾的普及战&#xff0c;加上此前已经普及的智能座舱&#xff0c;舱驾智能的「科技平权」进一步加速行业启动「线控底盘」上车窗…

【Node.js】express框架

目录 1初识express框架 2 初步使用 2.1 安装 2.2 创建基本的Web服务器 2.3 监听方法 2.3.1 监听get请求 2.3.2 监听post请求 2.4 响应客户端 2.5 获取url中的参数(get) 2.5.1 获取查询参数 2.5.2 获取动态参数 2.6 托管静态资源 2.6.1 挂载路径前缀 2.6.2 托管多…

树形DP(树形背包+换根DP)

树形DP 没有上司的舞会 家常便饭了&#xff0c;写了好几遍&#xff0c;没啥好说的&#xff0c;正常独立集问题。 int head[B]; int cnt; struct node {int v,nxt; }e[B<<1]; void modify(int u,int v) {e[cnt].nxthead[u];e[cnt].vv;head[u]cnt; } int a[B]; int f[B]…

REACT--组件通信

组件之间如何进行通信&#xff1f; 组件通信 组件的通信主要借助props传递值 分为整体接收、解构接收 整体接收 import PropTypes from prop-types;//子组件 function Welcome(props){return (<div>hello Welcome,{props.count},{props.msg}</div>) }// 对 We…

【排序算法】六大比较类排序算法——插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序【详解】

文章目录 六大比较类排序算法&#xff08;插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序&#xff09;前言1. 插入排序算法描述代码示例算法分析 2. 选择排序算法描述优化代码示例算法分析 3. 冒泡排序算法描述代码示例算法分析与插入排序对比 4. 希尔排序算法描…

纠错检索增广生成论文

一、摘要 动机&#xff1a;RAG严重依赖于检索文档的相关性&#xff0c;如果检索出错&#xff0c;那么LLM的输出结果也会出现问题 解决方案&#xff1a;提出纠正性检索增强生成&#xff08;CRAG&#xff09;即设计一个轻量级的检索评估器&#xff0c;用来评估针对某个查询检索…

Java NIO与传统IO性能对比分析

Java NIO与传统IO性能对比分析 在Java中&#xff0c;I/O&#xff08;输入输出&#xff09;操作是开发中最常见的任务之一。传统的I/O方式基于阻塞模型&#xff0c;而Java NIO&#xff08;New I/O&#xff09;引入了非阻塞和基于通道&#xff08;Channel&#xff09;和缓冲区&a…

easelog(1)基础C++日志功能实现

EaseLog(1)基础C日志功能实现 Author: Once Day Date: 2025年2月22日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 注&#xff1a;本简易日志组件代码实现参考了Google …

Vue面试2

1.跨域问题以及如何解决跨域 跨域问题&#xff08;Cross-Origin Resource Sharing, CORS&#xff09;是指在浏览器中&#xff0c;当一个资源试图从一个不同的源请求另一个资源时所遇到的限制。这种限制是浏览器为了保护用户安全而实施的一种同源策略&#xff08;Same-origin p…

MongoDB应用设计调优

应用范式设计 什么是范式 数据库范式概念是数据库技术的基本理论&#xff0c;几乎是伴随着数据库软件产品的推出而产生的。在传统关系型数据库领域&#xff0c;应用开发中遵循范式是最基本的要求。但随着互联网行业的发展&#xff0c;NoSQL开始变得非常流行&#xff0c;在许多…