热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

.NetCore采取JWT方式进行身份认证

 验证与授权Authentication(身份认证)认证是系统对请求的用户进行身份识别的过程。Authorization(授权)授权是对认证通过后的用户进行权限分配的过程。授权简单

 

验证与授权

Authentication(身份认证)

认证是系统对请求的用户进行身份识别的过程。

Authorization (授权)

授权是对认证通过后的用户进行权限分配的过程。授权简单理解就是:识别认证后用户所拥有哪些权限,从而开放服务器相对应的资源;

我们通俗点来解释身份验证与授权:验证确认用户是否允许访问,授权给予登录后的用户指定权限标识(通过这个标识,服务端可允许用户进行访问和操作);

 

在进行讲解Jwt身份认证前我们来回一下过去我们在MVC、WebForm这些站点都是怎样进行身份认证的。

我想应该大多数都是基于COOKIE、Form表单的身份验证方式吧。

COOKIE验证方式的流程图如下:

.NetCore采取JWT方式进行身份认证

 


上面流程就是服务端在接收用户登录请求后创建COOKIE并保存在服务器上,然后通过Response.COOKIEs.Add将COOKIE返回客户端。

客户端浏览器可以记住服务器返回的COOKIE,记住后COOKIE值会存储在客户端硬盘上,下次访问站点时候Http请求头会携带COOKIE。

携带COOKIE的请求到服务端后,服务端进行验证,验证通过后即可正返回请求的资源,否则会跳转到登录页面。

COOKIE方式的缺点

了解到COOKIE方式的验证流程后可以发现它是对Http请求强加了一层“会话”,让我们的Http请求携带与身份认证相关的标识(COOKIE)。

那这种方式有什么不好的呢?我总结了下面几点:

1、对有多种客户端(APP、浏览器、Winform应用)请求的场景不好扩展;
2、对分布式架构的服务端不好扩展,客户端的请求不一定指向同一台服务器,每一台服务器都需存储针对已登录的用户COOKIE;
3、跨域访问问题;

 

Jwt身份验证方式

在多终端,分布式架构的服务无所不在的今天,COOKIE身份认证的方式显然是难以满足我们的,这个时候Jwt(Json Web Token)横空出世啦~ 

使用Jwt我们可以完美的解决上面的遗留问题(当然后面也会说到jwt本身存在的问题....)

我们先看下Jwt的身份验证流程:

 .NetCore采取JWT方式进行身份认证

根据流程图得知jwt是在返回Token给客户端后要求客户端在Http请求头里携带载有Jwt信息的Authorization对象。

服务端会通过密钥对Jwt信息进行解密和验证,验证通过后会返回客户端所请求的资源。

根据流程我们得知jwt至少依赖这几项:

1、服务端的密钥;

2、客户端请求需指定格式(请求头携带Token);

 

其中密钥是客户端接触不到的,客户端所拥有的其实就是服务端生成的Token,这个Token是由三部分组成:

1、Header(包含算法和Token的类型:jwt)

2、PayLoad(负载,可配置的一些标识数据,不要将敏感信息写入到PayLoad内)

3、验签

其中Header和PayLoad只是在服务端进行了base64转码,所以如果有人抓取了Http请求是可以轻易截取里面的数据,我们

使用过程中千万不要将一些敏感信息放置里面。想详细了解Jwt信息可以到官网看看,官网地址:https://jwt.io/

 

.Net Core进行Jwt身份认证

.NetCore上使用Jwt身份认证非常简单,我们在Startup.cs文件的ConfigureServices里加入以下代码:

 1   services.AddAuthentication(x =>
 2             {
 3                 x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
 4                 x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 5             }).AddJwtBearer(x =>
 6             {
 7                 //获取权限是否需要HTTPS
 8                 x.RequireHttpsMetadata = false;
 9                 //在成功的授权之后令牌是否应该存储在Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties中
10                 x.SaveToken = true;
11                 
12                 x.TokenValidatiOnParameters= new TokenValidationParameters
13                 {
14                     //是否验证秘钥
15                     ValidateIssuerSigningKey = true,
16                     IssuerSigningKey = new SymmetricSecurityKey(key),
17                     ValidateIssuer = false,
18                     ValidateAudience = false
19                 };
20             });

 

在Startup里的Configure方法必须添加下面这行代码,且要求写在 app.UseMvc();前面。

 app.UseAuthentication(); //引用身份认证服务

 

上面的关键代码是Startup里的代码。 它明确告知系统采取Jwt验证方式为默认的身份认证方式、秘钥的

生成方式,以及一些验证相关的参数配置。

OK,现在我们已经明确了验证方式了,那我们创建Token是在哪里创建的呢?

我们来看看下面代码:

 1         private TokenDto CreateToken(User user)
 2         {
 3             // JwtSecurityTokenHandler可以创建Token
 4             var tokenHandler = new JwtSecurityTokenHandler();
 5             var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
 6             DateTime tokenExpires = DateTime.Now.AddMinutes(3); //过期时间这里写死
 7             DateTime refRefreshTokenExpires = tokenExpires.AddMinutes(-1);
 8             var tokenDescriptor = new SecurityTokenDescriptor
 9             {
10                 Subject = new ClaimsIdentity(new Claim[]
11                 {
12                     //添加申明,申明可以自定义,可以无限扩展,对于后续的身份验证通过后的授权特别有用...
13                     new Claim(ClaimTypes.Name, user.Id.ToString()),
14                     new Claim("refRefreshTokenExpires",refRefreshTokenExpires.ToString()),
15                     new Claim("tokenExpires",tokenExpires.ToString())
16                 }),
17                 Expires = tokenExpires,
18                 IssuedAt = DateTime.Now, //Token发布时间
19                 Audience = "AuthTest", //接收令牌的受众
20                 //根据配置文件的私钥值设置Token
21                 SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
22             };
23             var token = tokenHandler.CreateToken(tokenDescriptor);
24             user.Token = tokenHandler.WriteToken(token);
25             TokenDto output = Mapper.Map(user);
26             output.RefRefreshToken = Guid.NewGuid().ToString();
27             output.RefRefreshTokenExpires = refRefreshTokenExpires.ToString("yyyy-MM-dd HH:mm:ss");
28             output.Token = user.Token;
29             UserRefreshTokenData(user, output);
30             return output;
31         }

上面代码是包含了 刷新Token和刷新Token时间的创建Token方法。 

我在验证用户账号密码正确后即调用上面方法将Token返回给客户端,要求客户端在后续的API里必须携带Token来进行访问。

Token的有效时间我在上面写死了为三分钟,即三分钟后访问需授权的接口都会报http响应码为401的错误,如果需要解决则

要求客户端在刷新时间内,携带刷新Token值、刷新时间来调用 刷新Token接口获取 刷新后的Token值。

刷新Token方法;

 1    public TokenDto RefreshToken(TokenDto oldTokenDto)
 2         {
 3             TokenDto output = new TokenDto();
 4             //如果有刷新Token值对应的用户则刷新Token以及RefRefreshToken
 5             var user = _users.FirstOrDefault(p => p.RefRefreshToken == oldTokenDto.RefRefreshToken
 6                                             && Convert.ToDateTime(oldTokenDto.RefRefreshTokenExpires) > DateTime.Now);
 7             if (user != null)
 8             {
 9                 output = CreateToken(user);
10             }
11             return output;
12         }

 

至此,.NetCore采取JWT验证身份方式就写好了,包含了刷新Token。

对了,还没有总结JWT的劣势,劣势我捋了下面几点:

1、没有一个很方便的撤销已颁发的JWT令牌方法;

2、续签(刷新Token)增加了客户端的工作量(需要客户端在请求前验证刷新Token时间);

3、Token的加密与解密是与开发者自定义的payload的大小有关,如果存储的东西越多自然执行的效率也会越低(建议存储少量信息);

不过上面问题也不大,撤销令牌可以采取黑名单方式,至于第2点其实问题可以与前端约定好流程即可;

 


推荐阅读
  • AppFog 是一个基于 CloudFoundry 的多语言 PaaS(平台即服务)提供商,允许用户在其平台上轻松构建和部署 Web 应用程序。本文将通过详细的图文步骤,指导读者如何在 AppFog 免费云平台上成功部署 WordPress,帮助用户快速搭建个人博客或网站。 ... [详细]
  • 本文详细解析了JSONP(JSON with Padding)的跨域机制及其工作原理。JSONP是一种通过动态创建``标签来实现跨域请求的技术,其核心在于利用了浏览器对``标签的宽松同源策略。文章不仅介绍了JSONP的产生背景,还深入探讨了其具体实现过程,包括如何构造请求、服务器端如何响应以及客户端如何处理返回的数据。此外,还分析了JSONP的优势和局限性,帮助读者全面理解这一技术在现代Web开发中的应用。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • MongoDB高可用架构:深入解析Replica Set机制
    MongoDB的高可用架构主要依赖于其Replica Set机制。Replica Set通过多个mongod节点的协同工作,实现了数据的冗余存储和故障自动切换,确保了系统的高可用性和数据的一致性。本文将深入解析Replica Set的工作原理及其在实际应用中的配置和优化方法,帮助读者更好地理解和实施MongoDB的高可用架构。 ... [详细]
  • 利用Apache构建高效稳定的Web服务器环境
    本文详细介绍了如何利用Apache构建高效稳定的Web服务器环境。首先,概述了Apache服务器的基本概念及其安装步骤,并深入探讨了相关配置文件的设置方法。接着,通过具体的实验环境示例,展示了服务端(域名:zhangpp63.cn,IP地址:192.168.1.63)和客户端的配置过程,确保读者能够全面理解并实际应用这些技术。此外,还提供了一些优化建议,以提高服务器的性能和稳定性。 ... [详细]
  • 考前准备方面,我的考试时间安排在上午11点至12点,只需提前20分钟到达考场的接待休息区即可。由于我居住在福田区,交通便利,可以选择多种方式前往考场。为了确保顺利通过考试,我建议考生提前熟悉考试流程和环境,并合理规划出行时间,以保持良好的心态和状态。此外,考前复习应注重理论与实践相结合,多做模拟题,加强对重点知识点的理解和掌握。 ... [详细]
  • Python与R语言在功能和应用场景上各有优势。尽管R语言在统计分析和数据可视化方面具有更强的专业性,但Python作为一种通用编程语言,适用于更广泛的领域,包括Web开发、自动化脚本和机器学习等。对于初学者而言,Python的学习曲线更为平缓,上手更加容易。此外,Python拥有庞大的社区支持和丰富的第三方库,使其在实际应用中更具灵活性和扩展性。 ... [详细]
  • HTTP请求与响应机制:基础概览
    在Web浏览过程中,HTTP协议通过请求和响应报文实现客户端与服务器之间的通信。当用户访问一个网页时,浏览器会发送一个HTTP请求报文至服务器,服务器接收到请求后,会生成并返回一个HTTP响应报文。这两种报文均包含三个主要部分:起始行、头部字段和消息体,确保了数据的有效传输和解析。 ... [详细]
  • 通过优化模板消息机制,本研究提出了一种高效的信息化推送方案。该方案利用获取的访问令牌(access token)和指定的模板ID,实现了精准且快速的信息推送,显著提升了用户体验和信息传递效率。具体实现中,通过调用相关API接口,确保了消息的准确性和及时性,为用户提供更加便捷的服务。 ... [详细]
  • Sapphire 测试网上线:首个支持 EVM 的隐私 ParaTime 环境
    Sapphire 测试网上线:首个支持 EVM 的隐私 ParaTime 环境 ... [详细]
  • 基于Node.js的高性能实时消息推送系统通过集成Socket.IO和Express框架,实现了高效的高并发消息转发功能。该系统能够支持大量用户同时在线,并确保消息的实时性和可靠性,适用于需要即时通信的应用场景。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • MVVM架构~mvc,mvp,mvvm大话开篇
    返回目录百度百科的定义:MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:ControllerPresenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模 ... [详细]
  • 本文将介绍一种扩展的ASP.NET MVC三层架构框架,并通过使用StructureMap实现依赖注入,以降低代码间的耦合度。该方法不仅能够提高代码的可维护性和可测试性,还能增强系统的灵活性和扩展性。通过具体实践案例,详细阐述了如何在实际开发中有效应用这一技术。 ... [详细]
  • 深入解析 Spring MVC 的核心原理与应用实践
    本文将详细探讨Spring MVC的核心原理及其实际应用,首先从配置web.xml文件入手,解析其在初始化过程中的关键作用,接着深入分析请求处理流程,包括控制器、视图解析器等组件的工作机制,并结合具体案例,展示如何高效利用Spring MVC进行开发,为读者提供全面的技术指导。 ... [详细]
author-avatar
鱼鱼de眼泪2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有