我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下
jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的controller中,将发放token与验证分离,token的失效时间,发证者,使用者等信息存放到config中。
1.配置:
在appsettings.json中增加配置
1
2
3
4
5
6
7
8
9
10
|
"Jwt" : {
"Issuer" : "issuer" , //随意定义
"Audience" : "Audience" , //随意定义
"SecretKey" : "abc" , //随意定义
"Lifetime" : 20, //单位分钟
"ValidateLifetime" : true , //验证过期时间
"HeadField" : "useless" , //头字段
"Prefix" : "prefix" , //前缀
"IgnoreUrls" : [ "/Auth/GetToken" ] //忽略验证的url
}
|
2:定义配置类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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.加密解密接口:
1
2
3
4
5
|
public interface IJwt
{
string GetToken(Dictionary< string , string > Clims);
bool ValidateToken( string Token, out Dictionary< string , string > Clims);
}
|
4.加密解密的实现类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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.创建中间件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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.中间件暴露出去
1
2
3
4
5
6
7
8
9
10
11
12
|
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中使用中间件:
1
|
app.UseJwt();
|
以1的配置为例:
除了请求 /auth/getToken 不需要加头信息外,其他的请求一律要求头信息中必须带着
1
|
userless:prefix (从Auth/GetToken中获取到的token)
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/zzfstudy/p/10922384.html