一、jwt概述
json web token(jwt)是一种轻量级的身份认证机制,广泛应用于分布式系统中的用户认证。它通过紧凑的json格式存储用户身份信息,并使用数字签名确保信息的完整性和真实性。与传统的基于session的认证相比,jwt具有无状态、可扩展、跨平台等优势,特别适合于微服务架构和前后端分离的应用场景。
jwt的核心优势在于:
- 无状态:服务器不需要存储会话信息,减轻服务器负担
- 跨平台:基于标准json格式,可在不同语言和平台间传递
- 自包含:令牌包含所有必要的用户信息,减少数据库查询
- 可扩展:支持自定义声明,满足不同业务需求
- 安全性:通过数字签名确保信息不被篡改
二、jwt工作原理
jwt认证的核心流程如下:
- 用户登录:用户提供用户名和密码进行登录
- 生成token:服务器验证成功后,生成包含用户身份信息的jwt令牌
- 返回token:服务器将jwt令牌返回给客户端
- 存储token:客户端存储jwt令牌(通常存储在localstorage或cookie中)
- 请求携带token:客户端后续请求时,在http头部携带jwt令牌
- 验证token:服务器验证jwt令牌的有效性(签名验证、过期时间检查等)
- 处理请求:验证通过后,服务器处理请求并返回结果
jwt认证流程图
+----------+ 登录请求 +----------+
| | --------------> | |
| 客户端 | | 服务器 |
| | <-------------- | |
+----------+ 返回jwt令牌 +----------+
| |
| 携带jwt令牌的请求 |
| -----------------------------> |
| |
| <----------------------------- |
| 处理后的响应 |
v v三、jwt结构组成
jwt令牌由三部分组成,用小数点(.)分隔,格式为header.payload.signature:
1. header(头部)
header部分包含令牌类型(typ)和加密算法(alg),通常如下:
{
"alg": "hs256",
"typ": "jwt"
}其中,alg表示使用的加密算法(如hs256、rs256等),typ表示令牌类型。
2. payload(载荷)
payload部分包含用户身份信息和其他元数据,分为标准声明和自定义声明:
标准声明:
- iss:令牌颁发者
- sub:令牌主题(通常是用户id)
- aud:令牌受众
- exp:令牌过期时间
- iat:令牌颁发时间
- nbf:令牌生效时间
- jti:令牌唯一标识符
自定义声明:根据业务需求定义的字段,如用户角色、权限等。
示例:
{
"sub": "1234567890",
"name": "john doe",
"role": "admin",
"exp": 1678900000
}3. signature(签名)
signature部分是对header和payload的签名,用于验证令牌的完整性和真实性。服务器使用header中指定的算法,结合密钥对header和payload进行签名:
plaintext hmacsha256( base64urlencode(header) + "." + base64urlencode(payload), secretkey )
四、c#中实现jwt认证
1. 安装必要的包
在c#项目中,我们需要安装以下nuget包:
- system.identitymodel.tokens.jwt:用于生成和验证jwt令牌
- microsoft.aspnetcore.authentication.jwtbearer:提供jwt身份验证中间件
install-package system.identitymodel.tokens.jwt install-package microsoft.aspnetcore. authentication.jwtbearer
2. 配置jwt认证服务
在program.cs文件中,添加jwt认证服务配置:
program.cs
using microsoft.aspnetcore.authentication.
jwtbearer;
using microsoft.identitymodel.tokens;
using system.text;
var builder = webapplication.createbuilder(args);
// 添加jwt认证服务
builder.services.addauthentication
(jwtbearerdefaults.authenticationscheme)
.addjwtbearer(options =>
{
options.tokenvalidationparameters = new
tokenvalidationparameters
{
validateissuer = true, // 验证颁发者
validateaudience = true, // 验证受众
validatelifetime = true, // 验证过期时
间
validateissuersigningkey = true, // 验
证签名密钥
validissuer = builder.configuration
["jwt:issuer"], // 颁发者
validaudience = builder.configuration
["jwt:audience"], // 受众
issuersigningkey = new
symmetricsecuritykey(encoding.utf8.
getbytes(builder.configuration
["jwt:secretkey"])) // 签名密钥
};
});
// 添加授权服务
builder.services.addauthorization();
var app = builder.build();
// 使用认证和授权中间件
app.useauthentication();
app.useauthorization();
app.mapcontrollers();
app.run();3. 配置appsettings.json
在appsettings.json文件中添加jwt相关配置:
appsettings.json
应用
{
"jwt": {
"issuer": "yourissuer",
"audience": "youraudience",
"secretkey":
"yoursecretkeyhereshouldbelongenough"
},
"logging": {
"loglevel": {
"default": "information",
"microsoft.aspnetcore": "warning"
}
},
"allowedhosts": "*"
}4. 生成jwt令牌
创建一个authcontroller,实现用户登录和生成jwt令牌的功能:
authcontroller.cs
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 authcontroller : controllerbase
{
private readonly iconfiguration
_configuration;
public authcontroller(iconfiguration
configuration)
{
_configuration = configuration;
}
[httppost("login")]
public iactionresult login([frombody]
loginrequest request)
{
// 验证用户凭据(实际应用中应查询数据库)
if (request.username == "admin" &&
request.password == "password")
{
// 创建用户声明
var claims = new[]
{
new claim(claimtypes.name,
request.username),
new claim(claimtypes.role,
"admin"),
new claim(jwtregisteredclaimnames.
sub, "1234567890"),
new claim(jwtregisteredclaimnames.
jti, guid.newguid().tostring())
};
// 生成对称安全密钥
var key = new symmetricsecuritykey
(encoding.utf8.getbytes(_configuration
["jwt:secretkey"]));
// 生成签名凭据
var creds = new signingcredentials
(key, securityalgorithms.hmacsha256);
// 创建jwt令牌
var token = new jwtsecuritytoken(
issuer: _configuration
["jwt:issuer"],
audience: _configuration
["jwt:audience"],
claims: claims,
expires: datetime.now.addminutes
(30),
signingcredentials: creds);
// 返回jwt令牌
return ok(new
{
token = new
jwtsecuritytokenhandler().
writetoken(token),
expiration = token.validto
});
}
return unauthorized();
}
}
public class loginrequest
{
public string username { get; set; }
public string password { get; set; }
}5. 保护api端点
使用[authorize]属性保护api端点,只有携带有效jwt令牌的请求才能访问:
valuescontroller.cs
using microsoft.aspnetcore.authorization;
using microsoft.aspnetcore.mvc;
[apicontroller]
[route("api/[controller]")]
[authorize]
public class valuescontroller : controllerbase
{
[httpget]
public iactionresult get()
{
return ok(new string[] { "value1",
"value2" });
}
[httpget("{id}")]
[authorize(roles = "admin")]
public iactionresult get(int id)
{
return ok($"value {id}");
}
}五、jwt认证的注意事项
- 密钥安全:确保jwt密钥安全存储,避免硬编码在代码中
- 令牌过期时间:设置合理的令牌过期时间,平衡安全性和用户体验
- https传输:使用https协议传输jwt令牌,防止中间人攻击
- 令牌刷新机制:实现令牌刷新机制,避免用户频繁登录
- 敏感信息:不要在jwt中存储敏感信息,如密码等
- 权限控制:结合角色和权限声明,实现细粒度的访问控制
到此这篇关于c#中运用jwt用户认证的实现的文章就介绍到这了,更多相关c# jwt用户认证内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论