目录
-
- [一、先搞懂:JWT 是什么?(生活类比 + 核心流程)](#一、先搞懂:JWT 是什么?(生活类比 + 核心流程))
-
- [1. 生活类比:JWT = 景区电子门票](#1. 生活类比:JWT = 景区电子门票)
- [2. JWT 核心认证流程图](#2. JWT 核心认证流程图)
- [3. 核心价值](#3. 核心价值)
- [二、第一步:项目配置与 Nuget 包引用](#二、第一步:项目配置与 Nuget 包引用)
-
- [1. 环境要求](#1. 环境要求)
- [2. 安装 Nuget 包(两种方式)](#2. 安装 Nuget 包(两种方式))
-
- [方式 1:Nuget 包管理器](#方式 1:Nuget 包管理器)
- [方式 2:程序包管理器控制台](#方式 2:程序包管理器控制台)
- [方式 3:.NET CLI 命令](#方式 3:.NET CLI 命令)
- [三、第二步:appsettings.json 配置 JWT 核心参数](#三、第二步:appsettings.json 配置 JWT 核心参数)
- [四、第三步:Program.cs 注册 JWT 认证服务(核心代码)](#四、第三步:Program.cs 注册 JWT 认证服务(核心代码))
- [五、第四步:编写 JWT 令牌生成工具类](#五、第四步:编写 JWT 令牌生成工具类)
- [六、第五步:编写登录接口 + 受保护接口](#六、第五步:编写登录接口 + 受保护接口)
-
- [1. 登录接口(无需认证,生成 Token)](#1. 登录接口(无需认证,生成 Token))
- [2. 受保护接口(需要 JWT 认证才能访问)](#2. 受保护接口(需要 JWT 认证才能访问))
- [七、高频踩坑大全(90% 的新手都栽过!)](#七、高频踩坑大全(90% 的新手都栽过!))
-
- [1. 中间件顺序错误(最常见)](#1. 中间件顺序错误(最常见))
- [2. JWT 密钥太短 / 泄露](#2. JWT 密钥太短 / 泄露)
- [3. Issuer/Audience 前后端不一致](#3. Issuer/Audience 前后端不一致)
- [4. 令牌过期 / 服务器时间不同步](#4. 令牌过期 / 服务器时间不同步)
- [5. 前端请求头格式错误](#5. 前端请求头格式错误)
- [6. 忘记注册认证服务](#6. 忘记注册认证服务)
- 八、测试验证(Postman/Swagger)
- 总结
在前后端分离成为主流的今天,传统的 Session/Cookie 认证已经力不从心 ------ 跨域、分布式、移动端适配全是痛点。而JWT(JSON Web Token) 就是解决这些问题的「万能钥匙」!
今天这篇专栏,我会手把手带你完成ASP.NET Core JWT 认证完整配置,从 Nuget 引用、代码编写到高频踩坑全解析,用生活类比让你秒懂,新手也能直接 CV 跑通!

一、先搞懂:JWT 是什么?(生活类比 + 核心流程)
1. 生活类比:JWT = 景区电子门票
- 传统 Session:你去景区买票,工作人员把你的信息记在本子上,你只拿一个编号,每次进门都要查本子(服务器存储状态);
- JWT 认证 :景区给你一张加密电子票,上面写着你的身份、有效期、权限,票自己拿着,进门时工作人员扫码验证(票里自带信息,服务器不存储)。
2. JWT 核心认证流程图
否
是
否
是
前端:用户输入账号密码
后端:验证账号密码正确性
验证通过?
返回错误:账号密码无效
后端生成JWT令牌,返回给前端
前端存储Token:LocalStorage/Cookie
前端请求接口:请求头携带Authorization: Bearer Token
后端:验证JWT令牌合法性/有效期
验证通过?
返回401:未授权
授权访问接口,返回数据
3. 核心价值
1.无状态 :服务器不存储用户信息,分布式部署无压力;
2.跨域支持 :完美适配前后端分离、小程序、APP;
3.安全可控:加密签名、过期时间、权限声明全自定义。
二、第一步:项目配置与 Nuget 包引用
1. 环境要求
2. 安装 Nuget 包(两种方式)
方式 1:Nuget 包管理器
VS 中右键项目 → 管理 Nuget 程序包 → 浏览 → 搜索**Microsoft.AspNetCore.Authentication.JwtBearer ** → 安装最新稳定版。
方式 2:程序包管理器控制台
bash
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
方式 3:.NET CLI 命令
bash
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
三、第二步:appsettings.json 配置 JWT 核心参数
我们把 JWT 的密钥、颁发者、过期时间等配置写在配置文件,方便后期修改。
json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
// JWT配置节点
"JwtSettings": {
"SecretKey": "LongLongSecretKey@1234567890ABCDEF", // 密钥:越长越安全,至少16位
"Issuer": "MyBackendServer", // 令牌颁发者(你的后端服务)
"Audience": "MyFrontendClient", // 令牌接收者(你的前端)
"ExpiresMinutes": 60 // 令牌过期时间:60分钟
},
"AllowedHosts": "*"
}
✅ 小节重点
- SecretKey:绝对不能泄露!相当于你的令牌「签名钥匙」,泄露后任何人都能伪造令牌;
- ExpiresMinutes :不建议设置过长,建议 30~120 分钟,配合刷新 Token 使用;
3.Issuer 和 Audience:前后端必须保持一致,否则验证失败。
四、第三步:Program.cs 注册 JWT 认证服务(核心代码)
这是 JWT 生效的核心步骤 ,我们需要在 Program.cs 中注册认证、授权服务,并启用中间件。
完整代码(.NET 6+ 顶级语句)
csharp
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// 1. 添加控制器服务
builder.Services.AddControllers();
// 2. 从配置文件读取JWT参数
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = jwtSettings["SecretKey"];
var issuer = jwtSettings["Issuer"];
var audience = jwtSettings["Audience"];
var expiresMinutes = Convert.ToDouble(jwtSettings["ExpiresMinutes"]);
// 3. 注册JWT认证服务 ★核心代码★
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// 配置令牌验证参数
options.TokenValidationParameters = new TokenValidationParameters
{
// 验证颁发者
ValidateIssuer = true,
ValidIssuer = issuer,
// 验证接收者
ValidateAudience = true,
ValidAudience = audience,
// 验证过期时间
ValidateLifetime = true,
// 验证签名密钥
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)),
// 过期时间容错值(防止服务器时间不同步)
ClockSkew = TimeSpan.Zero
};
// 可选:配置JWT认证失败的自定义返回信息
options.Events = new JwtBearerEvents
{
OnChallenge = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json";
var result = new { code = 401, message = "未授权:请先登录获取Token" };
context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(result));
return Task.CompletedTask;
}
};
});
// 4. 注册授权服务
builder.Services.AddAuthorization();
var app = builder.Build();
// 中间件执行顺序:必须是 认证 → 授权 → 路由
app.UseHttpsRedirection();
// ★ 顺序绝对不能错 ★
app.UseAuthentication(); // 启用认证(第一步)
app.UseAuthorization(); // 启用授权(第二步)
app.MapControllers();
app.Run();
✅ 小节重点
- 中间件顺序:UseAuthentication 必须在 UseAuthorization 之前!先认证身份,再判断权限;
- ClockSkew:设置为 0,严格校验过期时间,避免令牌超时仍能使用;
- 自定义 OnChallenge:让认证失败返回友好 JSON,而非默认的 HTML 页面。
五、第四步:编写 JWT 令牌生成工具类
我们封装一个通用工具类,用于用户登录成功后生成 JWT 令牌。
csharp
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace JwtDemo.Utils
{
/// <summary>
/// JWT令牌生成工具类
/// </summary>
public static class JwtTokenHelper
{
/// <summary>
/// 生成JWT Token
/// </summary>
/// <param name="configuration">配置文件</param>
/// <param name="userId">用户ID</param>
/// <param name="userName">用户名</param>
/// <param name="role">用户角色(admin/user)</param>
/// <returns>JWT令牌</returns>
public static string CreateToken(IConfiguration configuration, string userId, string userName, string role)
{
// 读取JWT配置
var jwtSettings = configuration.GetSection("JwtSettings");
var secretKey = jwtSettings["SecretKey"];
var issuer = jwtSettings["Issuer"];
var audience = jwtSettings["Audience"];
var expiresMinutes = Convert.ToDouble(jwtSettings["ExpiresMinutes"]);
// 1. 创建用户声明(存储用户信息,如ID、角色、权限)
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userId), // 用户ID
new Claim(ClaimTypes.Name, userName), // 用户名
new Claim(ClaimTypes.Role, role), // 用户角色
new Claim("CustomInfo", "自定义业务数据") // 自定义声明
};
// 2. 创建密钥对象
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
// 3. 创建签名凭证
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
// 4. 生成JWT令牌
var token = new JwtSecurityToken(
issuer: issuer,
audience: audience,
claims: claims,
expires: DateTime.Now.AddMinutes(expiresMinutes), // 过期时间
signingCredentials: credentials
);
// 5. 生成最终的Token字符串
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}
✅ 小节重点
- Claim(声明):存储在令牌里的用户信息,相当于门票上的「身份信息」;
- 角色声明:用于后续权限控制,必须用ClaimTypes.Role类型;
- 令牌加密:固定使用HmacSha256算法,安全性最高。
六、第五步:编写登录接口 + 受保护接口
1. 登录接口(无需认证,生成 Token)
csharp
using Microsoft.AspNetCore.Mvc;
using JwtDemo.Utils;
namespace JwtDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
private readonly IConfiguration _configuration;
// 注入配置文件
public LoginController(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 用户登录:验证账号密码,生成JWT Token
/// </summary>
[HttpPost]
public IActionResult Login(string userName, string password)
{
// 模拟数据库验证账号密码(实际项目替换为真实校验)
if (userName == "admin" && password == "123456")
{
// 登录成功,生成Token
var token = JwtTokenHelper.CreateToken(_configuration, "1001", userName, "admin");
return Ok(new
{
code = 200,
message = "登录成功",
token = token,
expiresIn = 60 // 过期时间(分钟)
});
}
// 登录失败
return Ok(new { code = 400, message = "账号或密码错误" });
}
}
}
2. 受保护接口(需要 JWT 认证才能访问)
csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace JwtDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
// 全局添加[Authorize]:整个控制器需要认证
[Authorize]
public class UserController : ControllerBase
{
/// <summary>
/// 获取用户信息:必须携带有效Token才能访问
/// </summary>
[HttpGet("info")]
public IActionResult GetUserInfo()
{
// 从JWT令牌中读取用户信息
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var userName = User.Identity?.Name;
var role = User.FindFirst(ClaimTypes.Role)?.Value;
return Ok(new
{
code = 200,
message = "获取用户信息成功",
data = new { userId, userName, role }
});
}
/// <summary>
/// 仅管理员可访问:角色权限校验
/// </summary>
[HttpGet("admin")]
[Authorize(Roles = "admin")]
public IActionResult AdminApi()
{
return Ok(new { code = 200, message = "管理员接口访问成功" });
}
}
}
✅ 小节重点
1.[AllowAnonymous]:跳过认证,登录接口必须加;
2.[Authorize]:需要认证才能访问;
3.[Authorize(Roles = "admin")]:角色授权,仅指定角色可访问。
七、高频踩坑大全(90% 的新手都栽过!)
1. 中间件顺序错误(最常见)
- ❌ 错误:app.UseAuthorization() 在 app.UseAuthentication() 之前;
- ✅ 正确:先认证,后授权 ,顺序不可逆。
2. JWT 密钥太短 / 泄露
- ❌ 错误:密钥长度 < 16 位,或硬编码在代码中提交到 Git;
- ✅ 正确:密钥≥16 位,存配置文件,严格保密。
3. Issuer/Audience 前后端不一致
- ❌ 错误:后端配置Issuer="A",前端校验Issuer="B";
- ✅ 正确:前后端配置必须完全一致。
4. 令牌过期 / 服务器时间不同步
- ❌ 错误:未设置ClockSkew,导致令牌明明没过期却验证失败;
- ✅ 正确:设置ClockSkew = TimeSpan.Zero。
5. 前端请求头格式错误
- ❌ 错误:Authorization: Token xxxxx 或 直接写 Token;
- ✅ 正确:Authorization: Bearer 你的JWT令牌(Bearer + 空格 必须有)。
6. 忘记注册认证服务
- ❌ 错误:只写UseAuthentication,没写AddAuthentication;
- ✅ 正确:先注册服务,再启用中间件。
八、测试验证(Postman/Swagger)
1.运行项目,访问/api/Login,输入账号密码获取 Token;
2.访问/api/User/info,请求头添加Authorization: Bearer 你的Token;
3.验证结果:
- 携带有效 Token → 返回 200 + 用户信息;
- 无 Token / 无效 Token → 返回 401 未授权;
- 普通用户访问管理员接口 → 返回 403 禁止访问。
📢 结尾互动
今天的 JWT 认证全套配置就讲完啦!从代码 CV 到避坑,新手也能直接落地前后端分离项目!
互动问题
你在项目中用的是 JWT 还是 Session 认证?
你还遇到过哪些 JWT 踩坑问题?评论区告诉我!
总结
1.JWT = 前后端分离必备认证方案,无状态、跨域、安全;
2.核心三步:安装 Nuget 包→注册认证服务→生成 / 验证令牌 ;
3.避坑核心:中间件顺序、密钥安全、请求头格式 三大关键点;
4.代码全量可直接 CV 运行,适合.NET6/7/8 所有版本!
我是编程老伙计,关注我,下期带来 JWT 进阶实战!咱们评论区见~