.NetCore官⽅JWT授权验证的全过程
⽬录
什么是JWT?
什么时候应该使⽤JWT?
JWT结构是什么?
如何使⽤JWT
core的JWT验证授权
json检查
进阶
总结
什么是JWT?
JSON Web令牌(JWT)是⼀个开放标准(),它定义了⼀种紧凑且⾃包含的⽅式,⽤于在各⽅之间安全地传输信息作为JSON对象。由于此信息是经过数字签名的,因此可以被验证和信任。可以使⽤
秘密(使⽤HMAC算法)或使⽤RSA或ECDSA的公钥/私钥对对JWT进⾏签名。
尽管可以对JWT进⾏加密以提供双⽅之间的保密性,但我们将重点关注已签名的令牌。签名的令牌可以验证其中包含的声明的完整性,⽽加密的令牌则将这些声明隐藏在其他⽅的⾯前。当使⽤公钥/私钥
对对令牌进⾏签名时,签名还证明只有持有私钥的⼀⽅才是对其进⾏签名的⼀⽅。由于缺乏安全性,所以不能把如密码等敏感信息放在令牌中。
什么时候应该使⽤JWT?
以下是JSON Web令牌有⽤的⼀些情况:
授权:这是使⽤JWT的最常见⽅案。⼀旦⽤户登录,每个后续请求将包括JWT,从⽽允许⽤户访问该令牌允许的路由,服务和资源。单⼀登录是当今⼴泛使⽤JWT的⼀项功能,因为它的开销很⼩并且可以在不同的域中轻松使⽤。
信息交换:JSON Web令牌是在各⽅之间安全传输信息的好⽅法。因为可以对JWT进⾏签名(例如,使⽤公钥/私钥对),所以您可以确定发件⼈是他们所说的⼈。此外,由于签名是使⽤标头和有效负载计算的,因此您还可以验证内容是否未被篡改。
JWT结构是什么?
JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是:
标头
有效载荷
签名
因此,JWT通常如下所⽰。
标头:通常由两部分组成,令牌类型和使⽤的签名算法。
{
"alg": "HS256",
"typ": "JWT"
}
有效载荷:有三种说明类型,预定义声明、公共声明和私有声明。声明名称仅是三个字符,因为JWT是紧凑的
预定义声明:包括iss(发出者), exp(到期时间), sub(主题), aud(受众)等,是推荐的但是不是强制的可以没有。
公共声明:公共声明,这个部分可以随便定义,但是要注意和 IANA JSON Web Token 冲突。
私有声明:这个部分是共享被认定信息中⾃定义部分。
签名:要创建签名部分,您必须获取编码的标头,编码的有效负载,机密,标头中指定的算法,并对其进⾏签名。
例如,如果要使⽤HMAC SHA256算法,则将通过以下⽅式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名⽤于验证消息在此过程中没有更改,并且对于使⽤私钥进⾏签名的令牌,它还可以验证JWT的发送者是它所说的真实⾝份。
组合在⼀起如下为输出是三个由点分隔的Base64-URL字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUyMDAiLCJhdWQiOlsiYXBpIiwiYXBpIl0sIkd1aWQiOiIzM2NhZmJkNS1jZWEyLTRjOWMtYWZlYS01MDYyZjM3YWUyOTAiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2x JvDHuowbOnWiyxMIFc9gG5rw1LSSc0xx68L31oRfxS0
如何使⽤JWT
每当⽤户想要访问受保护的路由或资源时,⽤户代理都应发送JWT,通常使⽤承载模式在Authorization标头中发送JWT 。标头的内容应如下所⽰:
Authorization: Bearer <token>
在某些情况下,这可以是⽆状态授权机制。服务器的受保护路由将在Authorization标头中检查有效的JWT ,如果存在,则将允许⽤户访问受保护的资源。如果JWT包含必要的数据,则可以减少查询数据
库中某些操作的需求,尽管这种情况并⾮总是如此。
如果令牌是在Authorization标头中发送的,则跨域资源共享(CORS)不会成为问题,因为它不使⽤cookie。
下图显⽰了如何获取JWT并将其⽤于访问API或资源:
1. 应⽤程序或客户端向授权服务器请求授权。这是通过不同的授权流程之⼀执⾏的。例如,典型的符合OpenID Connect的Web应⽤程序将/oauth/authorize使⽤授权代码流通过端点。
2. 授予授权后,授权服务器会将访问令牌返回给应⽤程序。
3. 该应⽤程序使⽤访问令牌来访问受保护的资源(例如API)。
请注意,使⽤签名的令牌,令牌中包含的所有信息都会暴露给⽤户或其他⽅,即使他们⽆法更改它。这意味着您不应将机密信息放⼊令牌中。
core的JWT验证授权
我们直接新建⼀个 core webapi的项⽬,我这⾥版本是3.1的
1. 先使⽤nuget安装:Microsoft.AspNetCore.Authentication.JwtBearer。注意版本和 core版本的兼容。net5的⽀持5.0.0+的版本,否则就⽤对应可以⽤的低版本吧。
2. 在appsettings.json配置⽂件中写好我们的 JWT 的配置参数如下:
"Jwt": {
"Secret": "your-256-bit-secret",
"Iss": "localhost:44355",
"Aud": "api"
}
3. 在Startup.cs的ConfigureServices⽅法中添加授权认证如下:
var jwtConfig = Configuration.GetSection("Jwt");
//⽣成密钥
var symmetricKeyAsBase64 = jwtConfig.GetValue<string>("Secret");
var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
var signingKey = new SymmetricSecurityKey(keyByteArray);
//认证参数
services.AddAuthentication("Bearer")
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,//是否验证签名,不验证的画可以篡改数据,不安全
IssuerSigningKey = signingKey,//解密的密钥
ValidateIssuer = true,//是否验证发⾏⼈,就是验证载荷中的Iss是否对应ValidIssuer参数
ValidIssuer = jwtConfig.GetValue<string>("Iss"),//发⾏⼈
ValidateAudience = true,//是否验证订阅⼈,就是验证载荷中的Aud是否对应ValidAudience参数
ValidAudience = jwtConfig.GetValue<string>("Aud"),//订阅⼈
ValidateLifetime = true,//是否验证过期时间,过期了就拒绝访问
ClockSkew = TimeSpan.Zero,//这个是缓冲过期时间,也就是说,即使我们配置了过期时间,这⾥也要考虑进去,过期时间+缓冲,默认好像是7分钟,你可以直接设置为0
RequireExpirationTime = true,
};
});
在Configure⽅法中添加 app.UseAuthentication() 和 app.UseAuthorization() 注意位置需要放置的位置:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>{ endpoints.MapControllers();});
}
4. ⽣成jwt令牌,在默认⽣成的控制器 WeatherForecastController 中添加如下⽣成令牌的⽅法:
[HttpPost]
public IActionResult Authenticate()
{
var jwtConfig = Configuration.GetSection("Jwt");
//秘钥,就是标头,这⾥⽤Hmacsha256算法,需要256bit的密钥
var securityKey = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfig.GetValue<string>("Secret"))), SecurityAlgorithms.HmacSha256);
//Claim,JwtRegisteredClaimNames中预定义了好多种默认的参数名,也可以像下⾯的Guid⼀样⾃⼰定义键名.
//ClaimTypes也预定义了好多类型如role、email、name。Role⽤于赋予权限,不同的⾓⾊可以访问不同的接⼝
//相当于有效载荷
var claims = new Claim[] {
new Claim(JwtRegisteredClaimNames.Iss,jwtConfig.GetValue<string>("Iss")),
new Claim(JwtRegisteredClaimNames.Aud,jwtConfig.GetValue<string>("Aud")),
new Claim("Guid",Guid.NewGuid().ToString("D")),
new Claim(ClaimTypes.Role,"system"),
new Claim(ClaimTypes.Role,"admin"),
};
SecurityToken securityToken = new JwtSecurityToken(
signingCredentials: securityKey,
expires: DateTime.Now.AddMinutes(2),//过期时间
claims: claims
);
//⽣成jwt令牌
return Content(new JwtSecurityTokenHandler().WriteToken(securityToken));
}
5. 使⽤jwt控制接⼝的访问,我们在⼀个接⼝上添加⼀个特性 [Authorize(Roles ="admin")],表⽰需要有admin这个⾓⾊的jwt令牌才能访问,没有roles参数的话表⽰只要是可⽤的令牌就可以访问,多个role⾓⾊可以叠加多个特性:
[HttpGet]
[Authorize(Roles = "admin")]
[Authorize(Roles = "system")]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
6.测试,然后我们⽤postman就可以测试了,可以看到⾮常成功有数据。
进阶
认证的时候可以添加事件,如下⾯的认证失败事件、接收参数事件可以获取url上的参数作为令牌⽽不是通过http的请求头的Authorization。
services.AddAuthentication("Bearer")
.AddJwtBearer(o =>
{
o.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
context.Token = context.Request.Query["access_token"];
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
// 如果过期,则把<;是否过期>添加到,返回头信息中
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
总结
到此这篇关于.Net Core官⽅JWT授权验证的⽂章就介绍到这了,更多相关.Net Core官⽅JWT授权验证内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。