ASP.NET Core实现JWT授权与认证(1.理论篇)

  • ASP.NET Core实现JWT授权与认证(1.理论篇)已关闭评论
  • 205 次浏览
  • A+
所属分类:.NET技术
摘要

网络资源保护机制是一个鲜为人知的基本措施,比如我们会对网络相册设置密码并指定部分用户才可访问,又比如我们网盘的资源分享时设置的访问密码等等措施。这种资源保护的机制不光体现于此,作为软件从业人员对于我们开发的API的访问也是有一套保护机制的,那么对应到API的保护机制,也就是实现了一套完整的授权与认证体系,这也是基本的API接口标准。

1.授权与认证的作用

1.1.资源保护

网络资源保护机制是一个鲜为人知的基本措施,比如我们会对网络相册设置密码并指定部分用户才可访问,又比如我们网盘的资源分享时设置的访问密码等等措施。这种资源保护的机制不光体现于此,作为软件从业人员对于我们开发的API的访问也是有一套保护机制的,那么对应到API的保护机制,也就是实现了一套完整的授权与认证体系,这也是基本的API接口标准。

 

实现了授权与认证的API有以下的防护作用:

ASP.NET Core实现JWT授权与认证(1.理论篇)

1.2.传统授权

在我们传统的单机服务器架构模式中(应用程序只部署在一台服务器上),大多数Web应用都采用的是一种Seesion的身份验证方式。其中的效验流程概况如下:

 

1.用户在客户端浏览器第一次登陆系统时,Web服务器首先会效验用户名和密码的正确性,在效验成功后,Web服务器就会为当前用户创建一个Session对象,并将用户信息保存在Session中。

 2.当Session在服务器创建成功后,Web服务器会将生成的sessionID返回给客户端浏览器,客户端浏览器会将sessionID保存在Cookie中。

 3.当客户端浏览器再次访问服务器时,就会向服务器发送sessionID。服务器在接收处理请求时就会判断这个sessionID对应的Session信息,是否进行登录过并有相应的身份信息。然后根据对应的身份信息,进行对该用户的权限判断,看是否能访问相应的资源。

 ASP.NET Core实现JWT授权与认证(1.理论篇)

1.3.传统授权的局限

当网站业务规模和访问量的逐步发展扩张后,传统的单机服务器架构模式不在满足应用需求,这个时候服务器架构就会从单台演变为多台服务器的架构模式(集群、分布式等)。

 那么在这种多台服务器的架构模式中,对于传统的session的身份验证方式就会产生“局限”。因为基于Seesion默认的规则上,session是不能跨服务器共享数据的。

 这就是意味着,用户在第一次访问应用时,分配到A服务器登陆验证成功后,第二次访问应用时分配到B服务器时,对于B服务器而言,用户就是一个未登陆未验证的用户。

 ASP.NET Core实现JWT授权与认证(1.理论篇)

当然,如何去解决session跨服务器共享数据的方案也存在,但这种“补救式”的措施并非一套标准规范的授权认证体系。而本文将有讲解的重点JWT,它就是一套标准化授权认证体系,并且可以解决session身份验证方式存在的短板问题。


2.介绍JWT

2.1.什么是JWT

JWT(JSON Web Token),但从字义上来解释的话,它其实就是用于在Web应用中的一种JSON格式令牌。它一般传递在“身份提供者”和“服务提供者”之间,“身份提供者”需要通过JWT作为一种声明自身安全信息的令牌,从而得到“服务提供者”的信任,以便于从服务器获取相应的资源。

 JWT不光体现在令牌信息本身,它更是一种标准化的数据传输规范,以及作为一个开放的标准(RFC 7519),定义了一种简洁的、自包含的方法只要是在系统之间传输简短,但却需要一定安全等级的数据时,都可以使用JWT规范来传输。

 所以JWT作为了时下流行的授权与认证方案,它并不局限于某个开发平台,在其他语言框架中都有基于JWT规范的实现方案。另外在应用层面,JWT还被广泛的适用于分布式站点的单点登陆中。

 

2.2.JWT具有的好处

1.通用:基于JSON格式的通用性,所以JWT是可以进行跨语言的,像Java、JavaScript、PHP、Python等很多语言都可以使用。

2.紧凑:JWT的构成非常简单,占用的字节很小,可以将其方在HTTP请求报文头Header、URL、Cookie中进行传输。

3.扩展:JWT包含了常用的身份验证结构信息,并且支持自定义结构,另外不在依赖服务端创建Seesion存储信息,非常易于应用的扩展。

 

 2.3.JWT在Web中的请求流程

ASP.NET Core实现JWT授权与认证(1.理论篇)

对上图的流程补充描述如下:

1.客户端在登陆时向授权服务系统发起请求,以便申请“令牌”;

2.授权服务根据用户身份,生成一张专属“令牌”,该“令牌”以JWT格式规范返回给客户端;

3.客户端将获取到的“令牌”放到HTTP报文的Headers中后,向接口服务发起请求。

4.接口服务收到请求后,会从HTTP报文的Headers中获取“令牌”,并从“令牌”中解析出该用户的身份权限信息,然后判断做出相应的处理,从而决定是否允许访问对应的数据资源


3.JWT信息结构

JWT主要由三部分组成:头信息(Header)、消息体(Payload)、签名(Signature)。

3.1.头信息(Header)

头信息(Header)主要由两个部分组成:alg、typ。alg表示JWT的签名算法,一般有两个选择,默认使用的是HS256,另外一种是RS256。typ代表的是Token的类型。对应的JSON表现形式如下:

{   "alg":"HS256",   "typ":"JWT" }

3.2.消息体(Payload)

消息体(Payload)又叫做“载荷”,可以根据JWT的预定义结构或自定义的结构存放信息,一般包括用户信息或产品信息等。另外Payload中的存放的信息,在ASP.NET Core的验证模型“Claims Based Authentication”又有一种概念叫做“Claim(声明)”。

 

什么是Claim

Claim是对被验证主体特征的一项描述,就拿登陆中的被验证主体用户而言,那么对应的Claim包括:

“用户名是zhangsan”,“email是[email protected]”,“手机号码是15654541212”。在Claim当中还包括ClaimType,ClaimType代表描述信息的类型,以上的例子而言,其中ClaimType包括:用户名、email、手机号码。

 将上面Claim和ClaimType概念对应到现实中的事物来看,比如“检查驾照”,驾驶员对于交警就是一个被验证的主体,驾照中的“驾驶员姓名:章某某”、“身份证号码:4545454545”等一些描述信息就相当于是一个Claim。

 对于一个被验证主体(用户)而言,肯定不会仅仅存在单个Claim,而会存在多个Claim。那么对于多个Claim构成的数据结构就是“ClaimsIdentity”,可以把“ClaimsIdentity”理解为是被验证主体的“证件”。另外,“ClaimsIdentity”的持有者也就是被验证主体被称为“ClaimsPrincipal”。

 

通常一个简单的载荷JSON如下:

{  "iss":"WebApi",  "aud":"JD-ERP",   "exp":"1650445011" }

3.3.签名(Signature)

签名实际上是一个加密的过程,基于特定内容和指定算法生成的一段标识,作为验证接收方传递信息是否被篡改的依据。JWT签名作为JWT结构的一部分,其中的内容是包括:Header、PayLoad、密钥,然后通过签名算法将三者生成特定字符串。

 

在JWT签名算法中,一般有两个选择,一种是默认的HS256,另一种就是RS256。

RS256是一种“非对称加密算法”,它拥有一组密钥(公钥和私钥),私钥用于加密(签名),公钥用于解密(验证签名)。而HS256则是一种“对称加密算法”,加密(签名)和解密(验证签名)都使用同一种密钥。基于这两种算法的理解,在实际的应用当中使用RS256签名方式会更加安全。

3.4.内容表现形式

JWT会基于一种对象结构生成特定格式的字符串,字符串中根据JWT的结构也对应了有三个部分,分别由“.”号分割。我们可以通过JWT官方的站点(https://jwt.io/)来查看JWT全部表现形式,以及可以对其进行分析。

 ASP.NET Core实现JWT授权与认证(1.理论篇)

 

 上图左侧区域的数据,其中红色部分是“消息头”,紫色部分是“载荷”,它们都是基于JSON格式的数据上进行了base64的编码,才变成了一种特定的字符。蓝色部分就是“签名”,它是由:消息头、载荷、密钥,三个JSON格式数据进行签名生成的一种特定字符。

上图右侧区域的数据,是将JWT的Token字符串放在左侧区域解析出来的,通过解析出来的JSON数据就可以方便做一些调试分析。另外,在底部的“签名”区域,就可以清晰的看出我们签名字符串是通过什么样的方式生成的。其中的密钥部分是需要我们手动输入的,输入后就可以验证左侧的Token是否有效。


 4.结尾

本文主要介绍了关于JWT的理论部分,其中主要包括:作用、应用场景、概念、以及对应的结构等。其中弄懂这些概念也不是一蹴而就的,需要结合实际的操作进行演练才能更有深刻的体会。那么在下一个章节,我会主要介绍如何通过代码一步步在ASP.NET Core中实现JWT的授权与认证。