.net core webapi jwt 更为清爽的认证
程序员文章站
2022-03-20 12:00:56
我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下 jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的controller中,将发放token与验证分离,token的失效时间,发证者,使用者等信息存放到co ......
我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下
jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的controller中,将发放token与验证分离,token的失效时间,发证者,使用者等信息存放到config中。
1.配置:
在appsettings.json中增加配置
"jwt": { "issuer": "issuer",//随意定义 "audience": "audience",//随意定义 "secretkey": "abc",//随意定义 "lifetime": 20, //单位分钟 "validatelifetime": true,//验证过期时间 "headfield": "useless", //头字段 "prefix": "prefix", //前缀 "ignoreurls": [ "/auth/gettoken" ]//忽略验证的url }
2:定义配置类:
internal class jwtconfig
{
public string issuer { get; set; }
public string audience { get; set; }
/// <summary>
/// 加密key
/// </summary>
public string secretkey { get; set; }
/// <summary>
/// 生命周期
/// </summary>
public int lifetime { get; set; }
/// <summary>
/// 是否验证生命周期
/// </summary>
public bool validatelifetime { get; set; }
/// <summary>
/// 验证头字段
/// </summary>
public string headfield { get; set; }
/// <summary>
/// jwt验证前缀
/// </summary>
public string prefix { get; set; }
/// <summary>
/// 忽略验证的url
/// </summary>
public list<string> ignoreurls { get; set; }
}
3.加密解密接口:
public interface ijwt { string gettoken(dictionary<string, string> clims); bool validatetoken(string token,out dictionary<string ,string> clims); }
4.加密解密的实现类:
install-package system.identitymodel.tokens.jwt
public class jwt : ijwt { private iconfiguration _configuration; private string _base64secret; private jwtconfig _jwtconfig = new jwtconfig(); public jwt(iconfiguration configration) { this._configuration = configration; configration.getsection("jwt").bind(_jwtconfig); getsecret(); } /// <summary> /// 获取到加密串 /// </summary> private void getsecret() { var encoding = new system.text.asciiencoding(); byte[] keybyte = encoding.getbytes("salt"); byte[] messagebytes = encoding.getbytes(this._jwtconfig.secretkey); using (var hmacsha256 = new hmacsha256(keybyte)) { byte[] hashmessage = hmacsha256.computehash(messagebytes); this._base64secret= convert.tobase64string(hashmessage); } } /// <summary> /// 生成token /// </summary> /// <param name="claims"></param> /// <returns></returns> public string gettoken(dictionary<string, string> claims) { list<claim> claimsall = new list<claim>(); foreach (var item in claims) { claimsall.add(new claim(item.key, item.value)); } var symmetrickey = convert.frombase64string(this._base64secret); var tokenhandler = new jwtsecuritytokenhandler(); var tokendescriptor = new securitytokendescriptor { issuer = _jwtconfig.issuer, audience = _jwtconfig.audience, subject = new claimsidentity(claimsall), notbefore = datetime.now, expires = datetime.now.addminutes(this._jwtconfig.lifetime), signingcredentials =new signingcredentials(new symmetricsecuritykey(symmetrickey), securityalgorithms.hmacsha256signature) }; var securitytoken = tokenhandler.createtoken(tokendescriptor); return tokenhandler.writetoken(securitytoken); } public bool validatetoken(string token, out dictionary<string, string> clims) { clims = new dictionary<string, string>(); claimsprincipal principal = null; if (string.isnullorwhitespace(token)) { return false; } var handler = new jwtsecuritytokenhandler(); try { var jwt = handler.readjwttoken(token); if (jwt == null) { return false; } var secretbytes = convert.frombase64string(this._base64secret); var validationparameters = new tokenvalidationparameters { requireexpirationtime = true, issuersigningkey = new symmetricsecuritykey(secretbytes), clockskew = timespan.zero, validateissuer = true,//是否验证issuer validateaudience = true,//是否验证audience validatelifetime = this._jwtconfig.validatelifetime,//是否验证失效时间 validateissuersigningkey = true,//是否验证securitykey validaudience = this._jwtconfig.audience, validissuer = this._jwtconfig.issuer }; securitytoken securitytoken; principal = handler.validatetoken(token, validationparameters, out securitytoken); foreach (var item in principal.claims) { clims.add(item.type, item.value); } return true; } catch (exception ex) { return false; } } }
5.定义获取token的controller:
在startup.configureservices中注入 ijwt
services.addtransient<ijwt, jwt>();//jwt注入
[route("[controller]/[action]")] [apicontroller] public class authcontroller : controllerbase { private ijwt _jwt; public authcontroller(ijwt jwt) { this._jwt = jwt; } /// <summary> /// gettoken /// </summary> /// <returns></returns> [httppost] public iactionresult gettoken() { if (true) { dictionary<string, string> clims = new dictionary<string, string>(); clims.add("username", username); return new jsonresult(this._jwt.gettoken(clims)); } } }
6.创建中间件:
public class usejwtmiddleware { private readonly requestdelegate _next; private jwtconfig _jwtconfig =new jwtconfig(); private ijwt _jwt; public usejwtmiddleware(requestdelegate next, iconfiguration configration,ijwt jwt) { _next = next; this._jwt = jwt; configration.getsection("jwt").bind(_jwtconfig); } public task invokeasync(httpcontext context) { if (_jwtconfig.ignoreurls.contains(context.request.path)) { return this._next(context); } else { if (context.request.headers.trygetvalue(this._jwtconfig.headfield, out microsoft.extensions.primitives.stringvalues authvalue)) { var authstr = authvalue.tostring(); if (this._jwtconfig.prefix.length > 0) { authstr = authvalue.tostring().substring(this._jwtconfig.prefix.length+1, authvalue.tostring().length -(this._jwtconfig.prefix.length+1)); } if (this._jwt.validatetoken(authstr, out dictionary<string, string> clims)) { foreach (var item in clims) { context.items.add(item.key, item.value); } return this._next(context); } else { context.response.statuscode = 401; context.response.contenttype = "application/json"; return context.response.writeasync("{\"status\":401,\"statusmsg\":\"auth vaild fail\"}"); } } else { context.response.statuscode = 401; context.response.contenttype = "application/json"; return context.response.writeasync("{\"status\":401,\"statusmsg\":\"auth vaild fail\"}"); } } } }
7.中间件暴露出去
public static class useusejwtmiddlewareextensions
{
/// <summary>
/// 权限检查
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static iapplicationbuilder usejwt(this iapplicationbuilder builder)
{
return builder.usemiddleware<usejwtmiddleware>();
}
}
8.在startup.configure中使用中间件:
app.usejwt();
以1的配置为例:
除了请求 /auth/gettoken 不需要加头信息外,其他的请求一律要求头信息中必须带着
userless:prefix (从auth/gettoken中获取到的token)
推荐阅读
-
.net core webapi jwt 更为清爽的认证详解
-
ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新
-
.NET Core的JWT认证的学习
-
.net core webapi jwt 更为清爽的认证详解
-
ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库
-
ASP.NET Core 基于JWT的认证(一)
-
ASP.NET Core使用JWT认证授权的方法
-
AntDesign Pro + .NET Core 实现基于JWT的登录认证功能
-
ASP.NET Core 基于JWT的认证(二)
-
ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新