对于 登陆,身份,授权这之类的操作,我们最常用的几种方法无非就是 cookie session token
这三者的差别
https://www.cnblogs.com/moyand/p/9047978.html
这篇文章写的非常好
cookie和session到了微服务和负载均衡需要扩展时,就显得力不从心,而token这种无状态的身份验证就更加适合
JWT
所谓JWT就是 JSON WEB Token 是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成:头信息(header),消息体(payload)和签名(signature)。
头信心中会生命算法类型:
header = '{"alg":"HS256","typ":"JWT"}'
消息体:
payload = '{"loggedInAs":"admin","iat":1422779638}'//iat表示令牌生成的时间
只有签名是加密的,但是你真实中看到的token样子是长这样
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxIiwiVXNlck5hbWUiOiJhZG1pbnMiLCJpYXQiOiIxNTc2MTE3MTY0IiwibmJmIjoiMTU3NjExNzE2NCIsImV4cCI6MTU3NjExNzg4NCwiaXNzIjoiRnl0U29hIiwiYXVkIjpbIkNtcyIsIkNtcyJdLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbnMifQ.1HFSPephhGAUqwl0zRvTvd-ow7_6E_S78DGvaiY_UnQ
一眼看上去好像都被加密了,但其实上header和payload只是进行了base64的编码,仔细的话你可以发现token里面有两个点“.”,进行分隔
认证与授权
首先我们要弄清楚认证(Authentication)和授权(Authorization)的区别,以免混淆了。认证是确认的过程中你是谁,而授权围绕是你被允许做什么,即权限。显然,在确认允许用户做什么之前,你需要知道他们是谁,因此,在需要授权时,还必须以某种方式对用户进行身份验证。
开始代码
首先,我写了一个JWTapi的.netcore3.0作为授权服务,一个TestApi2作为业务api
首先看JWTapi
仅仅需要一个谁都能访问的接口,提供登陆服务,(查询登陆结果那个地方,应该做数据库的匹配,我节省时间写了个假的)
生成token的方法中要设置Issuer,Audience,JWTSecretKey,这三者要与认证服务中的相同才能解开
接下来来看Testapi2
Testapi2作为一个业务api,作为一个被访问者,不是谁都能见我的,你要到达某个级别,才能见到我,所以要对来访的人进行认证
所以要在ConfigureServices中,添加
services.AddAuthentication()
.AddJwtBearer(JwtAuthorizeAttribute.JwtAuthenticationScheme, o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证Issuer
ValidateAudience = true,//是否验证Audience
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ValidateLifetime = true,//是否验证超时 当设置exp和nbf时有效 同时启用ClockSkew
ClockSkew = TimeSpan.FromSeconds(30),//注意这是缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟
ValidAudience = Configuration["JwtAuth:Audience"],//Audience
ValidIssuer = Configuration["JwtAuth:Issuer"],//Issuer,这两项和前面签发jwt的设置一致
RequireExpirationTime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtAuth:SecurityKey"]))//拿到SecurityKey
};
o.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
// 如果过期,则把<是否过期>添加到,返回头信息中
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
这里面的Issuer,Audience,SecurityKey这三者,要与生成token时使用的一样
然后找一个controller,加上某种角色才可以访问的限制
使用postman模拟登陆
会得到一串token值,将这串token放入postman,选择Testapi2中的api进行发送
可以发送,获得200的返回值,如果token写错了,就会得到
401的返回值
注意,认证中的规则只会在网站第一次访问时跑一次,也就是AddJwtBearer中的代码只会在网站第一次访问时跑一次,如果你的加密Audience,Issuer,SecurityKey变了,也需要重新启动一次网站
本例子gitee地址
https://gitee.com/hallejuyahaha/OcelotDemo-Dotnet2.2