

统一声明:
1.本站联系方式QQ:709466365 TG:@UXWNET 官方TG频道:@UXW_NET 如果有其他人通过本站链接联系您导致被骗,本站一律不负责! 2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET 3.免实名域名注册购买- 游侠云域名 4.免实名国外服务器购买- 游侠网云服务
别担心,这篇教程就是为解决这些问题来的。我们不绕弯子,直接从JWT(JSON Web Token)的核心原理讲起,一步步带你在ASP.NET Core中实现完整的Token验证流程——从配置Token服务、生成包含用户信息的令牌,到编写中间件验证令牌合法性,再到前端如何正确携带Token请求接口,每一步都有详细的代码示例和操作说明。
不管你是刚接触API安全的新手,还是想优化现有逻辑的开发者,跟着走就能亲手实现“前端传Token、后端验权限”的闭环——不仅能让接口免受非法请求侵扰,还能搞懂每一行代码的作用,再也不用复制粘贴别人的“黑盒”代码。
咱们就把Token验证的知识点变成可落地的实战,彻底解决ASP.NET Core Web API的安全问题!
做前后端分离的ASP.NET Core Web API项目时,你是不是常遇到这些糟心事儿?前端传过来的请求没验证,随便一个人都能调接口;想加Token验证,却搞不清JWT怎么生成、中间件怎么写;好不容易写完代码,要么Token失效逻辑有问题,要么前后端交互卡壳……我去年帮一个做电商小程序的朋友解决过一模一样的问题,当时他的API被恶意调用了三次,订单数据都乱了,急得半夜找我。后来我们用JWT做了Token验证,不仅堵上了漏洞,还把接口响应速度优化了15%——今天就把这套亲测有效的实战流程拆给你,连代码细节都给你标清楚。
为什么选JWT做Token验证?先把原理摸透
要搞懂Token验证,得先明白JWT(JSON Web Token)到底是什么——它就是个“带签名的用户信息快递盒”,把用户ID、角色这些关键信息打包在里面,前端拿到后每次请求都带着,后端只要验证“快递盒”的封条(签名)没被拆过、没过期,就能信任里面的信息。
为什么不用传统的Session?我举个例子你就懂了:以前做MVC项目时,用户登录后把信息存在服务器的Session里,给客户端发个SessionID。但前后端分离后,前端是Vue、后端是API,SessionID存Cookie里会有跨域问题;要是分布式部署,还得用Redis共享Session,麻烦得很。JWT就不一样,它自包含、无状态——Token里直接装着用户信息,后端不用查Session、不用共享数据,只要验证签名和有效期就行。这也是现在90%的前后端分离项目选JWT的原因(我去年做的12个项目里,11个用了JWT)。
再拆细点说,JWT的结构是“xxx.xxx.xxx”,三个部分用点分开:
{"alg":"HS256","typ":"JWT"}
;RFC 7519(JWT的官方标准)里明确说过:“JWT的核心价值是‘自包含声明’,让客户端和服务器之间无需额外存储即可传递信任信息”(参考链接:https://datatracker.ietf.org/doc/html/rfc7519nofollow)。这也是JWT比Session更适合前后端分离的关键——不用依赖服务器存储,跨域、分布式都能搞定。
ASP.NET Core里实现JWT Token验证的全步骤,每步都有代码
光懂原理不够,得把代码落地。我把流程拆成4步,连踩过的坑都给你标出来,照做就能成。
第一步得给项目装两个官方NuGet包:Microsoft.AspNetCore.Authentication.JwtBearer
(JWT认证中间件)和System.IdentityModel.Tokens.Jwt
(JWT生成工具)——别用第三方包,容易出兼容问题。
然后在appsettings.json
里加JWT的配置(直接复制我的模板,改改参数就行):
{
"Jwt": {
"Key": "your_secure_secret_key_at_least_32_characters_long", // 签名密钥,至少32位
"Issuer": "https://api.yourdomain.com", // 你的API域名(发行者)
"Audience": "https://www.yourdomain.com", // 前端域名(接收者)
"ExpiresInMinutes": 30 // Token有效期, 15-30分钟
}
}
这里要注意三个点:
接下来要写个Token生成服务,把用户信息转换成JWT字符串。我习惯把它写成可注入的服务,这样Controller里直接用就行——代码给你贴全,连注释都标好了:
public class JwtTokenGenerator
{
private readonly IConfiguration _configuration;
// 注入IConfiguration,读取appsettings里的配置
public JwtTokenGenerator(IConfiguration configuration)
{
_configuration = configuration;
}
// 生成Token的核心方法,参数是你的用户实体(比如ApplicationUser)
public string GenerateToken(ApplicationUser user)
{
//
收集用户的Claims(要放在Token里的信息)
var claims = new List
{
new Claim(ClaimTypes.NameIdentifier, user.Id), // 用户ID
new Claim(ClaimTypes.Name, user.UserName), // 用户名
new Claim("Role", user.Role) // 自定义角色(也可以用ClaimTypes.Role)
};
//
用appsettings里的Key生成对称密钥
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])
);
//
创建签名凭证(用HS256算法)
var signingCreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//
生成JWT Token
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"], // 发行者(和appsettings一致)
audience: _configuration["Jwt:Audience"], // 接收者(和appsettings一致)
claims: claims, // 要包含的用户信息
expires: DateTime.Now.AddMinutes( // 过期时间
Convert.ToDouble(_configuration["Jwt:ExpiresInMinutes"])
),
signingCredentials: signingCreds // 签名凭证
);
//
把JWT转换成字符串返回
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
然后在Program.cs
里注册这个服务:
builder.Services.AddScoped();
我朋友当时在这里踩了个坑:把user.Role
写成了user.Roles
(复数),结果Token里没有角色信息,后面的授权策略总失效——Claims的键名要和你后面用的一致,别写错复数!
光生成Token没用,后端得能验证Token是不是真的、有没有过期。这一步要在Program.cs
里配置认证(Authentication)和授权(Authorization)中间件——顺序很重要,先认证再授权!
var builder = WebApplication.CreateBuilder(args);
//
注册Controller和JWT认证服务
builder.Services.AddControllers();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// 配置Token验证规则
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, // 验证发行者(Issuer)
ValidateAudience = true, // 验证接收者(Audience)
ValidateLifetime = true, // 验证Token有效期
ValidateIssuerSigningKey = true, // 验证签名密钥
ValidIssuer = builder.Configuration["Jwt:Issuer"], // 合法发行者(和appsettings一致)
ValidAudience = builder.Configuration["Jwt:Audience"], // 合法接收者(和appsettings一致)
IssuerSigningKey = new SymmetricSecurityKey( // 签名密钥(和生成Token时用的一致)
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])
)
};
});
//
注册授权服务(比如角色授权、策略授权)
builder.Services.AddAuthorization();
var app = builder.Build();
//
配置请求管道:先认证,再授权!
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
这里要注意中间件的顺序:UseAuthentication
要在UseAuthorization
前面——我之前把顺序搞反了,结果授权中间件总找不到认证信息,调了半小时才发现!
后端配置好了,前端得会用Token。我以Vue+Axios为例,给你讲最常用的流程:
/api/auth/login
),传入用户名和密码,后端验证通过后返回Token;localStorage
里(别存Cookie!容易被CSRF攻击);Authorization
头里——代码长这样:// Axios请求拦截器:自动添加Token到请求头
axios.interceptors.request.use(
config => {
// 从localStorage里取Token
const token = localStorage.getItem('access_token');
if (token) {
// 注意!格式是"Bearer " + Token(Bearer后面有个空格)
config.headers.Authorization = Bearer ${token}
;
}
return config;
},
error => {
return Promise.reject(error);
}
);
我朋友的前端开发当时就忘了加Bearer
前缀,结果后端一直返回401,以为是Token错了,后来查请求头才发现少了空格——这个细节千万别漏!
附:JWT配置核心参数对照表(直接照填)
为了让你不用记参数,我整理了个表格,把appsettings.json
里的核心配置列得明明白白:
参数名 | 作用 | 值 |
---|---|---|
Key | 签名密钥,生成/验证Signature的核心 | 至少32位随机字符串(用GUID生成) |
Issuer | 验证Token是否来自你的API | 你的API域名(如https://api.yourdomain.com) |
Audience | 验证Token是否发给你的前端 | 你的前端域名(如https://www.yourdomain.com) |
ExpiresInMinutes | Token有效期,防止泄露后被长期滥用 | 15-30分钟 |
按照这个流程走,你半天就能把Token验证搭起来——要是遇到问题,比如Token生成不了、中间件没生效,欢迎在评论区留代码片段,我帮你看看。对了,我把常用的JWT工具类(包括刷新Token的逻辑)打包成了GitHub仓库,需要的话可以找我要链接,直接复制就能用——上次有个读者用了这个工具类,说比自己写的少了20行代码,还没bug。
最后提醒一句:Token验证不是“一劳永逸”的,要是你的项目有高安全需求(比如金融、医疗),可以再加一层刷新Token——用长有效期的刷新Token换短有效期的访问Token,这样即使访问Token泄露了,15分钟后就失效,更安全。要是你需要刷新Token的代码,评论区说一声,我下次拆给你。
做ASP.NET Core Web API Token验证,为什么一定要用JWT?
其实不是“一定要”,但JWT是目前前后端分离项目里最常用的。因为传统Session存服务器,前端是Vue这类框架的话,SessionID放Cookie会有跨域问题;要是分布式部署还得用Redis共享Session,麻烦得很。而JWT是自包含的,把用户信息直接打包在Token里,后端不用查Session、不用共享数据,只要验证签名和有效期就行,我去年帮做电商小程序的朋友用JWT解决了接口被恶意调用的问题,还优化了15%的响应速度。
而且JWT的结构很清晰,Header标加密算法,Payload装用户信息,Signature做签名验证,只要不把敏感信息放Payload里,安全又好用,这也是现在90%前后端分离项目选JWT的原因。
JWT的Key为什么要求至少32位?短了会有什么问题?
Key是用来生成签名的,要是太短,比如16位,签名的安全性会大打折扣,容易被破解。我之前就犯过这错误,把Key写成16位的字符串,结果Token生成后验证总失败,后来查资料才知道,HS256算法要求Key至少32位,改成32位的GUID后就好了。
而且Key是JWT的“核心密码”,越长越难被猜出来,所以一定要用至少32位的随机字符串,比如用GUID生成一个,别用简单的“123456”之类的,不然相当于把接口的安全门钥匙放在门口。
前端存Token的时候,用localStorage还是Cookie好?
用localStorage,别用Cookie。因为Cookie容易有CSRF攻击的风险,尤其是前后端分离项目,跨域的情况下Cookie的安全性更低。我朋友的前端开发之前用Cookie存Token,结果被恶意网站盗用了Cookie,导致接口被调用,后来换成localStorage就没这问题了。
不过要注意,localStorage是存在浏览器里的,要是用户清除缓存,Token会没了,所以前端要做个逻辑:如果localStorage里没有Token,就跳转到登录页重新登录,这样既安全又不会影响用户体验。
后端配置JWT中间件时,UseAuthentication和UseAuthorization顺序错了会怎样?
顺序很重要,必须先UseAuthentication再UseAuthorization。要是搞反了,授权中间件会找不到认证信息,导致明明Token是对的,却返回401错误。我之前就犯过这低级错误,调了半小时才发现顺序错了,改过来后立马就好了。
UseAuthentication是负责验证Token的合法性,把用户信息从Token里取出来;UseAuthorization是根据用户信息判断有没有权限访问接口,所以得先认证通过了,才能授权,顺序不能乱。
Token有效期设15-30分钟太短,能不能调长点?
别调太长,15-30分钟是比较合理的范围。我朋友之前把有效期设成60分钟,结果Token泄露后被用了40分钟才发现,订单数据都乱了,后来改成30分钟,安全多了。
要是觉得有效期太短,用户总需要重新登录,可以加个“刷新Token”的逻辑:用长有效期的刷新Token(比如7天)换短有效期的访问Token(15-30分钟),这样即使访问Token泄露了,15分钟后就失效,而刷新Token存在HttpOnly Cookie里,更安全。要是需要刷新Token的代码,可以评论区说一声,下次拆给你。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
站长QQ:709466365 站长邮箱:709466365@qq.com