.net core webapi jwt 更为清爽的认证详解
我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下
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:定义配置类:
internalclassJwtConfig { publicstringIssuer{get;set;} publicstringAudience{get;set;} //////加密key /// publicstringSecretKey{get;set;} //////生命周期 /// publicintLifetime{get;set;} //////是否验证生命周期 /// publicboolValidateLifetime{get;set;} //////验证头字段 /// publicstringHeadField{get;set;} //////jwt验证前缀 /// publicstringPrefix{get;set;} //////忽略验证的url /// publicListIgnoreUrls{get;set;} }
3.加密解密接口:
publicinterfaceIJwt { stringGetToken(DictionaryClims); boolValidateToken(stringToken,outDictionary Clims); }
4.加密解密的实现类:
install-packageSystem.IdentityModel.Tokens.Jwt publicclassJwt:IJwt { privateIConfiguration_configuration; privatestring_base64Secret; privateJwtConfig_jwtConfig=newJwtConfig(); publicJwt(IConfigurationconfigration) { this._configuration=configration; configration.GetSection("Jwt").Bind(_jwtConfig); GetSecret(); } //////获取到加密串 /// privatevoidGetSecret() { varencoding=newSystem.Text.ASCIIEncoding(); byte[]keyByte=encoding.GetBytes("salt"); byte[]messageBytes=encoding.GetBytes(this._jwtConfig.SecretKey); using(varhmacsha256=newHMACSHA256(keyByte)) { byte[]hashmessage=hmacsha256.ComputeHash(messageBytes); this._base64Secret=Convert.ToBase64String(hashmessage); } } //////生成Token /// ////// publicstringGetToken(Dictionary Claims) { List claimsAll=newList (); foreach(variteminClaims) { claimsAll.Add(newClaim(item.Key,item.Value)); } varsymmetricKey=Convert.FromBase64String(this._base64Secret); vartokenHandler=newJwtSecurityTokenHandler(); vartokenDescriptor=newSecurityTokenDescriptor { Issuer=_jwtConfig.Issuer, Audience=_jwtConfig.Audience, Subject=newClaimsIdentity(claimsAll), NotBefore=DateTime.Now, Expires=DateTime.Now.AddMinutes(this._jwtConfig.Lifetime), SigningCredentials=newSigningCredentials(newSymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature) }; varsecurityToken=tokenHandler.CreateToken(tokenDescriptor); returntokenHandler.WriteToken(securityToken); } publicboolValidateToken(stringToken,outDictionary Clims) { Clims=newDictionary (); ClaimsPrincipalprincipal=null; if(string.IsNullOrWhiteSpace(Token)) { returnfalse; } varhandler=newJwtSecurityTokenHandler(); try { varjwt=handler.ReadJwtToken(Token); if(jwt==null) { returnfalse; } varsecretBytes=Convert.FromBase64String(this._base64Secret); varvalidationParameters=newTokenValidationParameters { RequireExpirationTime=true, IssuerSigningKey=newSymmetricSecurityKey(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 }; SecurityTokensecurityToken; principal=handler.ValidateToken(Token,validationParameters,outsecurityToken); foreach(variteminprincipal.Claims) { Clims.Add(item.Type,item.Value); } returntrue; } catch(Exceptionex) { returnfalse; } } }
5.定义获取Token的Controller:
在Startup.ConfigureServices中注入IJwt
services.AddTransient();//Jwt注入 [Route("[controller]/[action]")] [ApiController] publicclassAuthController:ControllerBase { privateIJwt_jwt; publicAuthController(IJwtjwt) { this._jwt=jwt; } /// ///getToken /// ///[HttpPost] publicIActionResultGetToken() { if(true) { Dictionary clims=newDictionary (); clims.Add("userName",userName); returnnewJsonResult(this._jwt.GetToken(clims)); } } }
6.创建中间件:
publicclassUseJwtMiddleware { privatereadonlyRequestDelegate_next; privateJwtConfig_jwtConfig=newJwtConfig(); privateIJwt_jwt; publicUseJwtMiddleware(RequestDelegatenext,IConfigurationconfigration,IJwtjwt) { _next=next; this._jwt=jwt; configration.GetSection("Jwt").Bind(_jwtConfig); } publicTaskInvokeAsync(HttpContextcontext) { if(_jwtConfig.IgnoreUrls.Contains(context.Request.Path)) { returnthis._next(context); } else { if(context.Request.Headers.TryGetValue(this._jwtConfig.HeadField,outMicrosoft.Extensions.Primitives.StringValuesauthValue)) { varauthstr=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,outDictionaryClims)) { foreach(variteminClims) { context.Items.Add(item.Key,item.Value); } returnthis._next(context); } else { context.Response.StatusCode=401; context.Response.ContentType="application/json"; returncontext.Response.WriteAsync("{\"status\":401,\"statusMsg\":\"authvaildfail\"}"); } } else { context.Response.StatusCode=401; context.Response.ContentType="application/json"; returncontext.Response.WriteAsync("{\"status\":401,\"statusMsg\":\"authvaildfail\"}"); } } } }
7.中间件暴露出去
publicstaticclassUseUseJwtMiddlewareExtensions { //////权限检查 /// ////// publicstaticIApplicationBuilderUseJwt(thisIApplicationBuilderbuilder) { returnbuilder.UseMiddleware (); } }
8.在Startup.Configure中使用中间件:
app.UseJwt();
以1的配置为例:
除了请求/auth/getToken不需要加头信息外,其他的请求一律要求头信息中必须带着
userless:prefix(从Auth/GetToken中获取到的token)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。