目录
-
- [一、先搞懂:JWT 到底是什么?(生活类比秒懂)](#一、先搞懂:JWT 到底是什么?(生活类比秒懂))
-
- [1.1 JWT 官方定义](#1.1 JWT 官方定义)
- [1.2 生活类比:酒店入住](#1.2 生活类比:酒店入住)
- [1.3 JWT 认证完整流程(流程图)](#1.3 JWT 认证完整流程(流程图))
- [二、环境准备:项目创建 + 依赖安装](#二、环境准备:项目创建 + 依赖安装)
-
- [2.1 创建项目](#2.1 创建项目)
- [2.2 安装 JWT 必需 NuGet 包](#2.2 安装 JWT 必需 NuGet 包)
- [三、第一步:后端配置 JWT(appsettings.json + Program.cs)](#三、第一步:后端配置 JWT(appsettings.json + Program.cs))
-
- [3.1 配置 JWT 参数(appsettings.json)](#3.1 配置 JWT 参数(appsettings.json))
- [3.2 注册 JWT 认证服务(Program.cs)](#3.2 注册 JWT 认证服务(Program.cs))
- [四、第二步:编写登录接口 + 生成 JWT Token](#四、第二步:编写登录接口 + 生成 JWT Token)
-
- [4.1 创建用户登录模型(LoginDto.cs)](#4.1 创建用户登录模型(LoginDto.cs))
- [4.2 创建登录控制器(LoginController.cs)](#4.2 创建登录控制器(LoginController.cs))
- [五、第三步:测试接口 + 前端携带 Token 访问](#五、第三步:测试接口 + 前端携带 Token 访问)
-
- [5.1 测试登录接口](#5.1 测试登录接口)
- [5.2 创建需要登录才能访问的接口](#5.2 创建需要登录才能访问的接口)
- [5.3 前端携带 Token 请求格式](#5.3 前端携带 Token 请求格式)
- [六、JWT 授权:区分角色权限(Admin/User)](#六、JWT 授权:区分角色权限(Admin/User))
- [七、新手必踩的 10 大深坑(90% 的人都栽过)](#七、新手必踩的 10 大深坑(90% 的人都栽过))
-
- [7.1 代码 / 配置类坑](#7.1 代码 / 配置类坑)
- [7.2 前后端交互坑](#7.2 前后端交互坑)
- [7.3 安全 / 业务坑](#7.3 安全 / 业务坑)
- 八、完整跨域配置(前后端分离必备)
- 九、总结
- 留言互动
前后端分离项目里,前端(Vue/React/ 小程序)和后端(API)是分家的,不能像传统项目用 Session/Cookie 存登录状态,JWT 就是前后端之间的 "安全通行证",今天从 0 到 1 写代码、讲流程、踩坑全避坑,新手也能直接 CV 跑通!

一、先搞懂:JWT 到底是什么?(生活类比秒懂)
1.1 JWT 官方定义
JWT 全称JSON Web Token ,是一种轻量级、自包含的令牌,用于在前后端之间安全传输身份信息,前后端分离认证的首选方案。
1.2 生活类比:酒店入住
- 你去酒店前台 = 前端调用登录接口
- 出示身份证、密码 = 提交用户名 + 密码
- 前台核对无误给你房卡 = 后端生成 JWT 令牌
- 进房间、刷电梯 = 前端携带 Token 访问需要登录的接口
- 房卡过期、伪造房卡打不开门 = Token 过期 / 无效 ,后端拒绝访问
核心逻辑 :JWT 就是后端给前端发的一次性合法房卡,前端随身携带,后端只认卡不认人,简单高效!
1.3 JWT 认证完整流程(流程图)
是
否
是
否
前端:用户输入账号密码
后端:登录接口验证账号密码
验证成功?
后端生成JWT Token返回前端
返回登录失败提示
前端存储Token:LocalStorage/Cookie
前端请求接口:请求头携带 Authorization: Bearer Token
后端:JWT中间件验证Token有效性
验证通过?
放行请求,返回业务数据
返回401未授权/403权限不足
二、环境准备:项目创建 + 依赖安装
2.1 创建项目
打开 Visual Studio/Rider,创建ASP.NET Core Web API项目(.NET 6/7/8 通用)。
2.2 安装 JWT 必需 NuGet 包
打开包管理器控制台执行:
bash
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
这个包是.NET 官方 JWT 认证核心包,必须安装!
三、第一步:后端配置 JWT(appsettings.json + Program.cs)
3.1 配置 JWT 参数(appsettings.json)
把 JWT 的密钥、过期时间、签发者等配置写在这里,方便后期修改:
json
"JwtSettings": {
"SecretKey": "YourSecretKey@1234567890!@#$%^&*()", // 密钥(越长越安全)
"Issuer": "MyBackendServer", // 令牌签发者(后端服务名)
"Audience": "MyFrontendClient", // 令牌接收者(前端客户端)
"ExpiresMinutes": 60 // Token过期时间(分钟)
}
3.2 注册 JWT 认证服务(Program.cs)
这是核心配置,告诉后端用 JWT 做身份认证:
csharp
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// 1. 读取appsettings中的JWT配置
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = Encoding.UTF8.GetBytes(jwtSettings["SecretKey"]);
// 2. 注册JWT认证服务
builder.Services.AddAuthentication(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(secretKey) // 密钥赋值
};
});
// 3. 添加控制器支持
builder.Services.AddControllers();
var app = builder.Build();
// 4. 启用认证、授权中间件(顺序不能错!)
app.UseAuthentication(); // 先认证(判断你是谁)
app.UseAuthorization(); // 后授权(判断你能做什么)
app.MapControllers();
app.Run();
四、第二步:编写登录接口 + 生成 JWT Token
4.1 创建用户登录模型(LoginDto.cs)
用于接收前端传递的账号密码:
csharp
/// <summary>
/// 登录参数接收类
/// </summary>
public class LoginDto
{
public string UserName { get; set; } // 用户名
public string Password { get; set; } // 密码
}
4.2 创建登录控制器(LoginController.cs)
核心:验证账号密码→生成 Token→返回给前端:
csharp
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
[ApiController]
[Route("api/[controller]")]
public class LoginController : ControllerBase
{
private readonly IConfiguration _configuration;
// 注入配置类
public LoginController(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 用户登录接口
/// </summary>
[HttpPost]
public IActionResult Login([FromBody] LoginDto loginDto)
{
// 1. 模拟验证账号密码(真实项目替换为数据库查询)
if (loginDto.UserName != "admin" || loginDto.Password != "123456")
{
return Ok(new { code = 400, msg = "账号或密码错误" });
}
// 2. 创建JWT令牌的核心信息(可以存用户ID、角色、权限等)
var claims = new[]
{
new Claim(ClaimTypes.Name, loginDto.UserName), // 用户名
new Claim(ClaimTypes.Role, "Admin"), // 用户角色(用于授权)
new Claim("UserId", "1001") // 自定义用户ID
};
// 3. 获取密钥
var secretKey = Encoding.UTF8.GetBytes(_configuration["JwtSettings:SecretKey"]);
var securityKey = new SymmetricSecurityKey(secretKey);
// 4. 生成签名(加密方式)
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
// 5. 生成JWT Token
var token = new JwtSecurityToken(
issuer: _configuration["JwtSettings:Issuer"],
audience: _configuration["JwtSettings:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(Convert.ToDouble(_configuration["JwtSettings:ExpiresMinutes"])),
signingCredentials: credentials
);
// 6. 生成最终的Token字符串
var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
// 7. 返回给前端
return Ok(new
{
code = 200,
msg = "登录成功",
data = new { token = tokenStr }
});
}
}
五、第三步:测试接口 + 前端携带 Token 访问
5.1 测试登录接口
用 Postman/Swagger 调用:POST https://localhost:7045/api/Login
请求体:
json
{
"UserName": "admin",
"Password": "123456"
}
返回结果:
json
{
"code": 200,
"msg": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
5.2 创建需要登录才能访问的接口
新建测试控制器,加上[Authorize]特性:
csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
[Authorize] // 关键:加此特性表示接口需要登录才能访问
public class TestController : ControllerBase
{
[HttpGet("info")]
public IActionResult GetUserInfo()
{
// 获取当前登录用户的信息
var userName = User.Identity?.Name;
var userId = User.FindFirst("UserId")?.Value;
return Ok(new
{
code = 200,
msg = "获取用户信息成功",
data = new { userName, userId }
});
}
}
5.3 前端携带 Token 请求格式
前端请求必须在请求头中携带:
http
Authorization: Bearer 你的Token值
⚠️注意:Bearer和 Token 之间必须有一个空格!
六、JWT 授权:区分角色权限(Admin/User)
JWT 不只能认证登录,还能做权限控制,比如:
- 普通用户只能查数据
- 管理员能增删改数据
用法:给接口 / 控制器加角色限制:
csharp
// 只有Admin角色能访问
[Authorize(Roles = "Admin")]
[HttpGet("admin")]
public IActionResult AdminApi()
{
return Ok("管理员专属接口");
}
// 普通用户和管理员都能访问
[Authorize(Roles = "Admin,User")]
[HttpGet("user")]
public IActionResult UserApi()
{
return Ok("普通用户接口");
}
七、新手必踩的 10 大深坑(90% 的人都栽过)
7.1 代码 / 配置类坑
- 中间件顺序错误: UseAuthentication必须在UseAuthorization之前,否则永远 401
- 密钥太短 / 太简单: 密钥长度不足会报错,必须≥16 位
- Token 生成时过期时间写反: 写成DateTime.Now.AddMinutes(-60),直接过期
- 请求头格式错误: Bearer后没空格、写成bearer小写、少写Authorization
7.2 前后端交互坑
- 前端跨域问题: 前后端分离必须配置跨域,否则请求被浏览器拦截
- Token 存储错误: 前端把 Token 存在 Session,刷新页面丢失
- Token 过期无处理: 前端没做过期拦截,用户一直卡在登录态
7.3 安全 / 业务坑
- 明文传输密码: 登录接口必须用 HTTPS,否则密码被抓包
- 密钥写死在代码里: 必须放在配置文件,方便环境切换
- JWT 存敏感信息: Token 可解码,不能存密码、身份证号
八、完整跨域配置(前后端分离必备)
新手最容易忘的一步,前端调用后端报跨域错误,直接加这段代码(Program.cs):
csharp
// 注册跨域服务
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin() // 允许所有地址
.AllowAnyHeader() // 允许所有请求头
.AllowAnyMethod(); // 允许所有请求方式
});
});
var app = builder.Build();
// 启用跨域(放在认证之前)
app.UseCors("AllowAll");
九、总结
- JWT 本质: 前后端分离的安全通行证,替代 Session/Cookie
- 核心流程: 登录验证→生成 Token→前端存储→请求头携带→后端鉴权
- 核心代码: JWT 注册配置、登录生成 Token、[Authorize]鉴权
- 关键避坑: 中间件顺序、请求头格式、跨域配置、Token 不存敏感信息
留言互动
大家在做 JWT 认证时还遇到过什么奇葩问题?评论区打出来,我一一解答!
原创不易,觉得有用的话点赞 + 收藏 + 关注,下期干货继续!