做为前后端分离项目中,授权认证常用token令牌做为身份认证的方式,对于jwt令牌的获取、验证、解析以及存储,分别示例如下:
需要安装两个nuget包,分别为:IdentityModel和Microsoft.AspNetCore.Authentication.JwtBearer
1、JWT令牌生成及获取
![](https://img-blog.csdnimg.cn/img_convert/0a3be4c85d1873a0119f069bb38bb7e0.gif)
//写Session或Cookies换成JWT
IList claims = new List {
new Claim(JwtClaimTypes.Id,admin.AdminId.ToString()),
new Claim(JwtClaimTypes.Name,loginDto.UserName),
new Claim(JwtClaimTypes.Email,loginDto.UserName),
new Claim(JwtClaimTypes.Role,string.Join(",", ""))
};
//JWT密钥
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:Bearer:SecurityKey"]));
//算法
var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//过期时间
DateTime expires = DateTime.UtcNow.AddHours(10);
//Payload负载
var token = new JwtSecurityToken(
issuer: configuration["JwtConfig:Bearer:Issuer"],
audience: configuration["JwtConfig:Bearer:Audience"],
claims: claims,
notBefore: DateTime.UtcNow,
expires: expires,
signingCredentials: cred
);
var handler = new JwtSecurityTokenHandler();
//生成令牌
string jwt = handler.WriteToken(token);
![](https://img-blog.csdnimg.cn/img_convert/78caf1e970d82657564547881afdd267.gif)
2、JWT验证部分
JWT在Startup中的配置,主要用来使用固定的配置密钥对JWT的Token进行有效性验证。
![](https://img-blog.csdnimg.cn/img_convert/f2b26237da17c8223ba23d01563f339c.gif)
//数据库连接
services.AddDbContext(action => {
action.UseSqlServer(Configuration.GetConnectionString("Default"));
});
services.AddCors(option =>
{
option.AddDefaultPolicy(policy =>
{
//对应客户端withCredentials,需要设置具体允许的域名
policy.WithOrigins("http://web.a.com:88").AllowCredentials();
policy.AllowAnyMethod();
policy.AllowAnyHeader();
});
});
services.AddAuthentication(option => {
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(
option => {
option.TokenValidationParameters = new TokenValidationParameters
{
//是否验证发行人
ValidateIssuer = true,
ValidIssuer = Configuration["Authentication:JwtBearer:Issuer"],//发行人
//是否验证受众人
ValidateAudience = true,
ValidAudience = Configuration["Authentication:JwtBearer:Audience"],//受众人
//是否验证密钥
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:JwtBearer:SecurityKey"])),
ValidateLifetime = true, //验证生命周期
RequireExpirationTime = true, //过期时间
ClockSkew = TimeSpan.Zero //平滑过期偏移时间
};
}
);
![](https://img-blog.csdnimg.cn/img_convert/3a52a54f92f0a767e988f0355f756deb.gif)
另外,还需要配置相应的认证中间件和授权中间件
![](https://img-blog.csdnimg.cn/img_convert/154a8ab92c469576d206a89bdbcecfea.gif)
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
string ApiName = "Rbac.Core";
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/V1/swagger.json", $"{ApiName} V1");
c.SwaggerEndpoint("/swagger/gp/swagger.json", "登录模块");
c.SwaggerEndpoint("/swagger/mom/swagger.json", "业务模块");
c.SwaggerEndpoint("/swagger/dm/swagger.json", "其他模块");
//路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc";
c.RoutePrefix = "";
});
}
//app.UseHttpsRedirection();
//静态文件中间件
app.UseStaticFiles();
//路由中间件
app.UseRouting();
//跨域
app.UseCors();
//认证中间件
app.UseAuthentication();
//授权中间件
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
![](https://img-blog.csdnimg.cn/img_convert/16ab04ec0e5be5771969e1b17ebe727f.gif)
经过上面配置,可以完成JWT令牌的生成及校验。
3、前端Axios的令牌保存及请求授权接口
前端接收到Api接口返回的token令牌后,应该把token保存起来,保存的位置可以是localStorage或sessionStorage,当访问授权接口时,从localStorage或sessionStorage中取出令牌,通过HTTP请求头进行访问。
![](https://img-blog.csdnimg.cn/img_convert/8b17df08376d450e739d0134119d9fdb.gif)
import router from '../router'
import axios from 'axios'
let baseUrl = "http://localhost:5000/api";
axios.defaults.baseURL = baseUrl;
axios.defaults.headers.common['Authorization'] = `bearer ${localStorage.getItem('token')}`;
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
router.push("/");
return Promise.reject(error);
});
export default {
baseUrl,
axios
}
![](https://img-blog.csdnimg.cn/img_convert/543d7b6fd3c617af0213904d5535bbc4.gif)
4、Swagger中的权限小锁配置
![](https://img-blog.csdnimg.cn/img_convert/ae585a130291eccd8ed5a5978f4d692c.gif)
//开启权限小锁
options.OperationFilter();
options.OperationFilter();
options.OperationFilter();
//在header中添加token,传递到后台
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传递)直接在下面框中输入Bearer {token}(注意两者之间是一个空格) \"",
Name = "Authorization",//jwt默认的参数名称
In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey
});
![](https://img-blog.csdnimg.cn/img_convert/5a9b29a9b8db0bba84f983e232f125bd.gif)
|