来源
用户认证的方式通常有两种,传统的session认证 和 基于token方式。
传统的session认证
sessionID的生成方式:
浏览器第一次访问服务器时,服务器创建一个session
,同时生成一个唯一的会话key,即sessionID
。
接着sessionID及session分别作为key和value保存到缓存中,也可以保存到数据库中,然后服务器把sessionID以cookie的形式发送给浏览器,浏览器下次访问服务器时直接携带上cookie中的sessionID,服务器再根据sessionID找到对应的session进行匹配
这里我们注意到两点:
-
sessionID
会自动由浏览器带上 -
session
是需要存储空间的
缺陷
传统的session认证,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来.
例如而随着认证用户的增多,服务端的开销会明显增大,这样在分布式的应用上,相应的限制了负载均衡器的能力,因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
基于token的鉴权机制
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
token的生成方式
浏览器第一次访问服务器时,服务器根据传过来的唯一标识userId
,通过一些算法,加一个密钥,生成一个token,接着通过base64编码将token返回给客户端。客户端将token保存起来,下次请求时需要带着token,服务器收到请求后,用相同的算法和密钥去验证token
这里我们注意到两点:
-
token需要代码才能带上
-
token可以不需要存储空间(JWT)(当然也有存入缓存的处理,特别是要进行revoke操作时),通过算法和密钥验证
token与sessionID的区别:
-
浏览器方面,是否直接带上
-
服务器方面,是否需要存储空间。
其实token与session的问题是一种时间与空间的博弈问题,session是空间换时间,而token是时间换空间。两者的选择要看具体情况而定。
JWT(JSON Web Token)
定义:
JWT(JSON Web Token) 是一个非常轻巧的规范,通过这个规范,可以传递可靠的安全信息,JWT常被用于前后端分离,可以和Restful API配合使用,常用于构建身份认证机制。
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).
该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
组成:
一个通常你看到的jwt,由以下三部分组成,它们分别是:
-
header
:主要声明了JWT的签名算法; -
payload
:主要承载了各种声明并传递明文数据; -
signture
:拥有该部分的JWT被称为JWS,也就是签了名的JWS;没有该部分的JWT被称为nonsecure JWT 也就是不安全的JWT,此时header中声明的签名算法为none。
signture
:将上面的header
和payload
编码后的字符串都用句号.连接在一起 提供一个密钥(secret)用头部所规定的算法加密就可以形成一个新的字符串
三个部分用·分割。形如xxxxx.yyyyy.zzzzz
的样式。
示例:
签名的目的:
最后一步签名的过程,实际上是对头部以及载荷内容进行签名。
所以,如果有人对头部以及载荷的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的。
服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。那么服务器应用是怎么知道我们用的是哪一种算法呢?别忘了,我们在JWT的头部中已经用alg字段指明了我们的加密算法了。
如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。