先简单说下JSON Web Token, 然后使用.NET Core内置的JWT验证机制.
Demo Source Code
AspNetCore JwtBearer Source Code
JSON Web Token
是什么
- JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间作为JSON对象安全地传输信息。
数据格式为: Header.Payload.Signature - 生成JWT Token
JWT的数据签名(Signature)是对Payload中的数据, 按照Header中指定的加密算法, 加上Server端的密钥进行签名生成的.- Signature = Payload + Algorithm(Header) + Security(私有)
- 通过签名反推出密钥的可能性很小, 并且密钥是Server端私有的, 可以定期更换
使用
JWT多用来验证请求的有效性
下面是简单的使用流程
- 用户post{username, password}到server, 请求token, server生成后返回token
- 得到token后, client端保存token: cookie/sessionStorage/localStorage
- 以后每当发起请求, 将token放到请求头: headers: { ‘Authorization’:
token
}, - server收到请求后, 会根据密钥及token中的payload生成新的signature并与token的中signature进行对比, 二者一致则验证通过
优势
- token的自验证性,减轻了服务端压力
server通过JWT的header, payload和signature就可以验证用户, 不需要再去查询数据库 - JWT不仅可以用于认证,也可以用于交换信息。有效使用JWT,可以降低服务器查询数据库的次数
JWT的payload中可以存储用户名, 权限, 过期时间等非安全信息, 解析token本身就可以取得 - JWT的自验证性, 非常适合单页面程序, 多点登录
- 通过将token放在请求头并使用https访问, 防范跨站脚本攻击(xss)和跨站攻击(csrf)
- 通过生成refresh token验证access token的实效性, 控制access token的有效时间, 解决无法回收token访问权限的问题
劣势
- 因为自验证性, 无法及时回收访问权限, token一旦被分发, 就会一直有效, 可以通过减少生效时间使用
.NET Core的JWT验证机制
.NET Core的JWT验证机制基于authentication中间件, 注入JWT服务后, 需要authenrize的请求都会使用token验证
Demo Source Code
AspNetCore JwtBearer Source Code
- 注入内置的JWT service
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey("your secret key"),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
- 生成有效的token
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("your token payload")
}),
// token的有效时间
Expires = DateTime.UtcNow.AddMinutes(),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
result = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));
4. 通过属性标签[Authorize]添加token验证的请求
[Authorize]支持class级别和接口级别的指定
[Authorize]
public class RepairController : ControllerBase
[Authorize]
[HttpGet("data")]
public ActionResult Get()