前言:本文解决的问题

  • 基于session 认证的不足
  • 基于 token 认证的过程
  • session VS tooken

1.传统基于Cookie 认证的过程

长期以来,基于Session的认证(Session based authentication)一直处于主流地位。由于http协议是无状态的,借助cookie,客户端登陆成功后,服务端就能识别其后续请求,而不需要每次都登陆。它是*有状态的(statefull),也就是服务端和客户端都需要保存生成的session**,也就是说在服务端需要在数据库中追踪session是否alive,客户端要把session写入cookie中。基本过程如下:

  • 客户端登陆,一般输入用户名和密码
  • 服务端如果验证通过,就会生成session,并把它存入数据库中
  • 客户端在浏览器上会产生cookie,并把session写入
  • 客户端后续有新的请求,都会在请求后携带sessIon,发给服务端
  • 如果客户端登陆出去(log out),该生成的session就会在客户端和服务端都被销毁 如下图:

将token设置在session token session用哪个_将token设置在session

基于Session 认证的不足
正如图片所示,服务端需要保存每个用户的session,这对于很多访问用户的情景来说,服务端的负担很重,需要大量的的资源来存储session;另一方面不能很好解决跨域资源共享问题Cross-Origin Resource Sharing (CORS)。最重要的是cookie的使用引入了很多不安全因素,招致了很多专门针对cookie的攻击。

2. 基于token的认证

近年来,基于token的认证开始成为主流,不管是单个网页,还是web app,还是*Internet of Things *。该认证方式是无状态的(stateless),客户端登陆成功后,服务端会生成一个token并把它返还给客户端,由于是无状态的,服务端不再保存该Token

问题来了,当客户端再发送请求时,服务端如何判断它曾经已经登陆了?类似Sesssion based authentication,客户端每次发送请求时也会携带Token。由于这里的Token是服务端用自己的密钥签名的,当它受到客户但的Token时,只需要再用自己的密钥去验证,就可以判断这个Token是不是刚自己签发的。这里面的核心就是用签名和验证,从而减轻了服务端的负担,无需再存储session,尤其是对于大型的分布式应用,减负很多。以下是具体的过程:

  • 客户端用自己的机密信息登陆,如用户名和密码
  • 服务端验证,验证通过,生成Token返还给客户端(一般用哈希算法,再加个随机数)。
  • 客户端把Token写入local storage(本地内存),后续请求都携带该Token
  • 服务端收到请求时验证Token,如果验证通过,则允许用户访问相应资源

将token设置在session token session用哪个_sed_02

问题

由于这里Token是后续用来登陆的唯一认证手段,如果用户关闭了网页,被其它别有用心的应用窃取到Token,拿它再来登陆就危险了。因此这里需要服务端给Tooken设置过期时间(expired time),不能太长,太长不安全;太短用户体验差。另外,当用户登出时,服务端要把当前Token设为黑名单(back list),防止被冒用。

3. 基于token的优点

  • 无状态,stateless

服务端无需保存生成的Token,它需要做的就是签发Token,并验证它。由于Token中是含有需要验证的所有信息(签名算法、用户信息、签名),这就让服务端负载减轻了很多

  • 交叉域和交叉域共享Cross-domain / CORS

Cookie和CORS在不同的域效果不好。而使用基于Token可以使API应用到不同的服务和域中。

  • 可以在JWT中存储数据 Store Data in the JWT

我们知道,现通用的Token based Authentication 就是JOSN Web Token(jwt)。JWT包含头部(header),载荷(claim set), 和签名(signature)。可以在载荷中存放预定义的元数据,只要是JOSON格式就可以了。

  • 不需要CSRF(cross-site-request-forgery)防护

由于不需要依赖Cookie,自然不用担心Cookie被截获,用户信息被伪造登陆问题。