踩坑不背锅,.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认证流程

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

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

JWT组成

官网 https://jwt.io/
JSON Web Tokens(JWT)有三部分构成:Header、Payload、VERIFY SIGNATURE,用英文句点分割(.) ,一般看起来例如:aaaaaaa.bbbbbbb.ccccccc。

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鉴权认证,有更好的想法欢迎留言指导

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

  1. ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范

    原文:ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范 IdentityServer实现以下规范: OpenID Connect OpenID Connect ...

  2. ASP.NET Core的身份认证框架IdentityServer4(3)-术语的解释

    ASP.NET Core的身份认证框架IdentityServer4(3)-术语的解释 原文:ASP.NET Core的身份认证框架IdentityServer4(3)-术语的解释 IdentityS ...

  3. 关于身份认证和鉴权过程

    关于身份认证和鉴权过程 开机信令流程 总结: 附 重要消息内容举例 LTE NAS EMM Plain OTA Outgoing Message -- Attach request Msg(含PDN ...

  4. ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露

    一.前言 在涉及到后端项目的开发中,如何实现对于用户权限的管控是需要我们首先考虑的,在实际开发过程中,我们可能会运用一些已经成熟的解决方案帮助我们实现这一功能,而在 Grapefruit.VuCore ...

  5. ASP.NET Core的身份认证框架IdentityServer4--入门【转】

    原文地址 Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Cor ...

  6. ASP.NET Core的身份认证框架IdentityServer4--(5)自定义用户登录(通过接口登录,无UI版本)...

    官网接口详解文档地址:文档地址 (PS:可通过接口名称搜索相应接口信息.) 源码地址:https://github.com/YANGKANG01/IdentityServer4-IdentityAut ...

  7. php 身份认证 claim,asp.net core cookie身份认证view视图中读取/读取User.Claims中的值实例...

    假设claim如下,q为查询出来的用户表结果集 var claims = new List(){ new Claim("UserId", q.Id.ToString()), new ...

  8. ASP.NET Core 实战:基于 Dapper 扩展你的数据访问方法

    ASP.NET Core 实战:基于 Dapper 扩展你的数据访问方法 一.前言 在非静态页面的项目开发中,必定会涉及到对于数据库的访问,最开始呢,我们使用 Ado.Net,通过编写 SQL 帮助类 ...

  9. 微服务架构下的安全认证与鉴权

    微服务架构下的安全认证与鉴权 转载自:https://mp.weixin.qq.com/s/qBJ_257IWn3cctqmKfJ7FQ 作者:王海龙,来自:EAWorld 现任普元云计算架构师,毕业 ...

最新文章

  1. Google人体图像分割模型Bodypix再次更新,针对Coral开发板优化,720p/30fps流畅运行...
  2. issubclass和isinstance 反射 内置方法(魔术方法)
  3. oracle快照太旧含义,全解ORA-1555快照太旧错误原理及解决方案
  4. 按钮点击_如何设置微信小程序按钮点击事件?
  5. java sqlserver 死锁_sqlserver数据库发生死锁处理
  6. Java实现hsql_java – 从类创建HSQL创建表查询
  7. swift(不同设备适配详解)
  8. 多个中间件_小T说:消息中间件,为什么用RabbitMQ及支持的场景
  9. 计算机毕业设计安卓旅游APP源码
  10. 机房维护 网拷_利用网络还原系统(远志)快速维护机房
  11. AUTOSAR接口类型及访问规则
  12. python获取b站视频封面及弹幕
  13. 程序员技能树的分层分级方法
  14. Python:实现ternary search三元搜索算法(附完整源码)
  15. Win10怎么默认用Windows照片查看程序打开图片
  16. 首个Nginx windows Stable 版--轻量级Web服务器Nginx 0.7.59
  17. 德克萨斯长角牛 --最短路径
  18. 未来十年的音视频,教科书级别的Android音视频开发教程,学完我成功“挤进”了抖音音视频开发岗
  19. 创建签名文件jks 乱码
  20. 【PTA】帅到没朋友(C语言)

热门文章

  1. 羊毛地毯可以用水洗吗
  2. 【校招VIP】产品经理之明确活动目的
  3. windows server 2008 R2无法共享文件夹,无法启用网络发现。
  4. 数据重塑_Google是否会重塑电话
  5. 计算机64位只有2g,电脑插了4G内存,但只有2G左右可以用,为什么 WIN7 64位
  6. 苹果计算机的桌面图是什么情况,苹果电脑开机后,只能显示电脑桌面,桌面图标都不能显示。怎么办?...
  7. c语言编译器error,KEIL C编译器常见警告与错误信息的解决办法
  8. 腾讯视频采集规则+发布模块(基于火车头全站采集与发布站点教程)
  9. 视频教程-Kali Linux 网络安全渗透测试-渗透测试
  10. unraid教程贴备忘