.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,outDictionaryClims);
}
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(DictionaryClaims)
{
ListclaimsAll=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,outDictionaryClims)
{
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)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。