700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > ASP.Net Core实战——身份认证(JWT鉴权)

ASP.Net Core实战——身份认证(JWT鉴权)

时间:2023-07-29 06:52:56

相关推荐

ASP.Net Core实战——身份认证(JWT鉴权)

踩坑不背锅,.NET Core 试深浅

关于鉴权认证什么是鉴权认证常见鉴权方式关于JWT认证JWT认证流程JWT组成JWT实践

关于鉴权认证


什么是鉴权认证

鉴权(authentication)是指验证用户是否拥有访问系统的权利。传统的鉴权是通过密码来验证的。这种方式的前提是,每个获得密码的用户都已经被授权。在建立用户时,就为此用户分配一个密码,用户的密码可以由管理员指定,也可以由用户自行申请。这种方式的弱点十分明显:一旦密码被偷或用户遗失密码,情况就会十分麻烦,需要管理员对用户密码进行重新修改,而修改密码之前还要人工验证用户的合法身份。

为了克服这种鉴权方式的缺点,需要一个更加可靠的鉴权方式。目前的主流鉴权方式是利用认证授权来验证数字签名的正确与否。

常见鉴权方式

Session机制Session 是一种HTTP存储机制,Session对象存储特定用户会话所需的属性及配置信息,目的是为无状态的HTTP提供的持久机制,把 User 信息存储到 Session 里。可以理解为一张短期通行证,给请求用户颁发短期证件,每次门岗检查短期卡号在备案名册中,允许通行,因为 SID 的不可预测性,暂且认为是安全的。

JWT机制

JWT即JSON Web Tokens,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),他可以用来安全的传递信息,因为传递的信息是经过加密算法加密过得。相当于一张长期通行证,给请求用户颁发长期证件,每次检查证件人信息,正确允许通行。

OAuth2机制OAuth的英文全称是Open Authorization,它是一种开放授权协议,由认证机构分别为服务与用户颁发凭证,用户授权服务使用凭证,接着服务使用此凭证去认证合法性,最终得到目标数据,如同调兵遣将时使用的两片虎符,由皇庭下发授权。

关于JWT认证


JWT认证流程

通过上图,我们可以看到它的授权流程

客户端通过请求服务端登录认证接口服务端用秘密创建JWT服务端将JWT返回浏览器客户端在授权报头上发送JWT服务端检查JWT签名从JWT获取用户信息服务端向客户端发送响应

JWT组成

官网 https://jwt.io/

JSON Web Tokens(JWT)有三部分构成:Header、Payload、VERIFY SIGNATURE,用英文句点分割(.) ,一般看起来例如:ccccc。

Header头信息,通常包含两部分:

type: 代表token的类型,这里使用的是JWT类型。alg: 代表使用的算法,例如HMAC SHA256或RSA.

Payload荷载信息,它包含一些声明Claim(实体的描述,例:用户信息和其他的一些元数据),声明分三类:

Reserved Claims,这是一套预定义的声明,并不是必须的,这是一套易于使用、操作性强的声明。包括:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等Plubic Claims,Private Claims,交换信息的双方自定义的声明

VERIFY SIGNATURE由头信息+荷载信息+密钥 组合之后进行加密得到,如使用的是HMAC SHA256算法,大致流程类似于: HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret)。VERIFY SIGNATURE字段被用来确认JWT信息的发送者是谁,并保证信息没有被修改。

JWT实践


想要实现JWT认证,需要做好两方面,Token令牌的签发与真实性验证。 首先准备一个用户信息对象(存放从数据库中查询到的相关信息)。

public class Tokens{/// <summary>/// ID/// </summary>public string ID{get; set; }/// <summary>/// 名称/// </summary>public string Login_name {get; set; }/// <summary>/// 手机/// </summary>public string Phone {get; set; }/// <summary>/// 邮箱/// </summary>public string Email {get; set; }/// <summary>/// 身份/// </summary>public string Sub {get; set; }}

接下来,使用以上部分信息生成Token

// 密钥,注意不能太短(这个是我在网上随便生成的)public static string secretKey {get; set; } = @"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMniN23tMkxBh6j3vCQ5c4JqsZ8p8NqNqeCjNQPDga9RtIFCt3/5n4aIyUaA0ONVMOHEt33g8EoayVZMKQGf4aPjConiAXYUYy540fs8r9l0oJyHWx+5at0nkKFfTtpgppXQRjWiWyeOq3RX9jhsdFKBPqbugZW4yjlt1QlSWaQtAgMBAAECgYEAm9vNt0w8XKrqtQQteDnyd2kvoBWdIN3lnMvjjfhOErAdjv2W9XIeOps36PpiSl/m0SYyEzipykxLzBgYQGzSoXgZwp91lmUKxVpCi6QgZU+VCR5q+Tr4BuLmi7GsJE0EwcpdC6jnOwbZXdhClLaQgRiiLPbiLw+CADbiHQqaRoECQQD0sE6VOqPW2eqPHH6mqaqy+owU0UiBCkW8xfBKqR74ufgnCveDLrfE+vxIqVBU1HN+/LqKZ1rPEkqPdjAUJk3pAkEA0zdYs12mu+as3araCPrnAppsZRRGizVKmKVB074W63NZ7SiXsEqDBj3fp1oeGo2OiKWCnjEmmtzpIvfVbzjlpQJBAOTQPhwUgwO2Mj7z0Ye+n47Q9s+8yYVJ+t7FZqgasIi9N04jVkPJGzZL0kGMez9okDyOz03/yo5bN3gieGFPVIkCQQCAMt2xsKwc7HwL50GDpdZFLDmSeGYA5I2sbNGxlXUP3+m7GqJHLFKunSt8xiPzdewHYH4RSj/mSyNuSALSCTTJAkBBN7BWA39VyvJDALVYqHDKNx0r5BwSTVk8wJvn7KKzB1YdVZrl/pIIi+uPbZwBJA80QXJu4sjCyc5XBzgQdsiv";// 生成JWT字符串public static string GetJWT(Tokens tokenModel){var claims = new List<Claim>{new Claim(JwtRegisteredClaimNames.Jti,tokenModel.Login_name),// 令牌颁发时间new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),// 过期时间 100秒new Claim(JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(100)).ToUnixTimeSeconds()}"),new Claim(JwtRegisteredClaimNames.Iss,"API"), // 签发者new Claim(JwtRegisteredClaimNames.Aud,"User") // 接收者};// 密钥var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));var creds = new SigningCredentials(key, SecurityAlgorithms.RsaSha512);JwtSecurityToken jwt = new JwtSecurityToken(claims: claims,// 声明的集合//expires: .AddSeconds(36), // token的有效时间signingCredentials: creds);var handler = new JwtSecurityTokenHandler();// 生成 jwt字符串var strJWT = handler.WriteToken(jwt);return strJWT;}

在这里会需要引用几个包:

Microsoft.IdentityModel.Tokens;System.IdentityModel.Tokens.Jwt;System.Security.Claims;

在Startup 注册Authentication服务与中间件

服务

//添加jwt验证:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,//是否验证IssuerValidateAudience = true,//是否验证AudienceValidateLifetime = true,//是否验证失效时间ValidateIssuerSigningKey = true,//是否验证SecurityKeyValidAudience = "User",//AudienceValidIssuer = "API",//Issuer,这两项和后面签发jwt的设置一致ClockSkew = TimeSpan.Zero, // // 默认允许 300s 的时间偏移量,设置为0IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenHelper.secretKey))//拿到SecurityKey};});

中间件

app.UseAuthentication();

在这里需要注意:签发者与接受者的对应

然后在Controller上加上关键代码,这样对应该路由的请求都会进行Authentication,当你的都头文件包含正确的Token就可以正常返回。

最后,在Swagger中试验一下

首先修改Swagger的options内容

//开启权限小锁options.OperationFilter<AddResponseHeadersFilter>();options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();//在header中添加token,传递到后台options.OperationFilter<SecurityRequirementsOperationFilter>();options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme{Description = "JWT授权(数据将在请求头中进行传递)直接在下面框中输入Bearer {token}(注意两者之间是一个空格) \"",Name = "Authorization",//jwt默认的参数名称In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)Type = SecuritySchemeType.ApiKey});

运行,我们可以在SwaggerUI页面看到多出来一个小锁Authorize

当请求没有携带Token,返回错误信息

先请求Token

点击上面的小锁Authorize,填入刚刚获取的Token信息(依据提示,在前面加上Bearer+space

然后就可以看到接口标签上的小锁是认证状态了,再次请求接口,就能正确获取数据。


仅仅简单的使用JWT鉴权认证,有更好的想法欢迎留言指导

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。