赞
踩
HTTP是一个无状态的协议,一次请求结束后,下次在发送服务用中,用户的认证和鉴权是非常重要得就不知道这个请求是谁发来的了(同一个IP不代表同一个用户),在Web的一环,实践中有多种可用方案,并且各有千秋。
在Web应用发展的初期,大部分采用基于Cookie-Session的会话管理方式,逻辑如下。
基于Session的方式存在多种问题,
这种模式最大的问题是,没有分布式架构,无法支持横向扩展。如果使用一个服务器,该模式完全没有问题。但是,如果它是服务器群集或面向服务的跨域体系结构的话,则需要一个统一的session数据库库来保存会话数据实现共享,这样负载均衡下的每个服务器才可以正确的验证用户身份。
例如,举一个实际中常见的单点登陆的需求:站点A和站点B提供同一公司的相关服务。现在要求用户只需要登录其中一个网站,然后它就会自动登录到另一个网站。怎么做?
一种解决方案是听过持久化session数据,写入数据库或文件持久层等。收到请求后,验证服务从持久层请求数据。该解决方案的优点在于架构清晰,而缺点是架构修改比较费劲,整个服务的验证逻辑层都需要重写,工作量相对较大。而且由于依赖于持久层的数据库或者问题系统,会有单点风险,如果持久层失败,整个认证体系都会挂掉。
另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法。
JWT是JSON Web Token 的缩写,是为了在网络应用环境间传递专明而执行的一种基于JSON的开放标准(RFC7519)。JWT本身没有定义何技术实现,它只是定义了一种基于作Token的会话管理的规则,涵盖Token需要包含的标准内容和Toke的生成过程,特别适用于分布式站点的单点登录(SSO)场景。
JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。
{
"姓名": "张三",
"角色": "管理员",
"到期时间": "2018年7月1日0点0分"
}
以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名
一个JWT Token 就像这样:(注意,JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。)
eyJhbGcioiJIUzI1NiISInR5cCI6IkpxVCJ9
.eyJ1c2VyX21kIjOyODAxODCyNZQ40DMyMZU4NSwiZXhwIjoxITkONTQwMjkxLC]pc3Mi0iJibHVlYmVsbcJ9
,lk ZrAtYGCeZhK3iupHxP1kgjBTzQTVTtXizYFx9wU
它是由.
分隔的三部分组成,这三部分依次是:
头部和负载以JSON形式存在,这就是JWT中的JSON,三部分的内容都分别单独经过了Base64编码,以.拼接成一个JT Token。
服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。
下面依次介绍这三个部分。
Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。
{
"alg": "HS256",
"typ": "JWT"
}
上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
这个 JSON 对象也要使用 Base64URL 算法转成字符串。
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。
JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法。
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。
Authorization: Bearer
另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。
(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。
(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用Cookie的浏览器环境中正常运行。
1、jwt基于json,非常方便解析
2、可以在令牌中自定义丰富的内容,易扩展;
3、通过非对称加密算法及数字签名技术。
而IWT的最大优势是服务端不再需要存储Sesion,使得服务端认证鉴权业务可以方便扩展,避免存储Sesion所需要引|入的Redis等组件,降低了系统架构复杂度。但这也是WT最大的劣势,由于有效期存储在Token 中,TToken一旦签发,就会在有效期内一直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的WIToken,如果需要禁用用户,单纯使用JWT就无法做到了。
常见的加密算法,
加密算法的种类:
1、可逆加密算法
加密后,密文可以解密得到原文
-般用于签名和认证。私钥服务器保存,用来加密,公钥客户拿着用于对于令牌或 者签名的解密或者校验使用.常见的非对称加密算法有: RSA、DSA(数字签名用)、ECC(移动设备用)、RS256 (采用 SHA-256 的 RSA 签名
2、不可逆加密算法
加密后,不能反向解密得到原文
一般用于敏感信息,密码,卡号等不可解密的信息
常见的不可逆加密算法有:MD5、SHA、HMAC 4.3.Base64编码 HS256:帶有SHA-256的HMAC
3、对称加密
4、非对称加密
base64号网络上最常见的用干传输8bit字节代码的编码方式之一、Base64编码可用于在 HTTP环境下传递较长的标识信息,采用Base64编码解码具有不可读性,即所编码的数据 不
会被人用肉眼所直接看到。
注意:Base64只是一种编码方式,不算加密方法。
前面讲的Token,都是Access Token,也就是访问资源接口时所需要的Token,还有另外一种Token,Refresh Token
Refresh Token的有效期会比交长,而Access Token 的有效期比较短。Refresh Token及过期时间是存储在服务器的数据库中,只有在申请新的Acesss Token时才会验证,不会对业务接口响应时间造成影响,也不需要向Session一样一直保持在内存中以应对大量的请求。
在JWT的实践中,引入Refresh Token,将会话管理流程改进如下
为什么要使用refresh token?为何会更安全?
普通的token方案 有效期设置过长不安全,过短需要频繁重新登录,体验差access token 有效期短,如果被盗损失更小,所以安全性更高。如果refresh token被盗了,想刷新access token的话,也需要提供过期的access token。i盗取难度增加。同时refresh token只有在第一次获取和刷新access token时才会在网络中传输被盗的风险远小于access token 从而在一定程度上更安全了一点所谓的更安全就是让盗取信息者更不容易获得而已。
golang实现代码 见 https://www.yuque.com/iveryimportantpig/huchao/qw5gv0?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。