『Java』用户登陆除了cookie和session,还有这么多解决方案( 三 )


2)每次传送cookie , 增加了请求的数量 , 对访问性能也有影响;
3)也有跨域问题 , 毕竟还是要用cookie 。
相比起第一种方式 , cookie-based方案明显还是要好一些 , 目前好多web开发平台或框架都默认使用这种方式来做会话管理 , 比如php里面yii框架 , 这是我们团队后端目前用的 , 它用的就是这个方案 , 以上提到的那些登录逻辑 , 框架也都已经封装好了 , 实际用起来也很简单;asp.net里面forms身份认证 , 也是这个思路 , 这里有一篇好文章把它的实现细节都说的很清楚:
http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html
前面两种会话管理方式因为都用到cookie , 不适合用在native app里面:native app不好管理cookie , 毕竟它不是浏览器 。 这两种方案都不适合用来做纯api服务的登录认证 。 要实现api服务的登录认证 , 就要考虑下面要介绍的第三种会话管理方式 。
3. token-based的管理方式 这种方式从流程和实现上来说 , 跟cookie-based的方式没有太多区别 , 只不过cookie-based里面写到cookie里面的ticket在这种方式下称为token , 这个token在返回给客户端之后 , 后续请求都必须通过url参数或者是http header的形式 , 主动带上token , 这样服务端接收到请求之后就能直接从http header或者url里面取到token进行验证:
『Java』用户登陆除了cookie和session,还有这么多解决方案
本文插图
这种方式不通过cookie进行token的传递 , 而是每次请求的时候 , 主动把token加到http header里面或者url后面 , 所以即使在native app里面也能使用它来调用我们通过web发布的api接口 。 app里面还要做两件事情:
1)有效存储token , 得保证每次调接口的时候都能从同一个位置拿到同一个token;
2)每次调接口的的代码里都得把token加到header或者接口地址里面 。
看起来麻烦 , 其实也不麻烦 , 这两件事情 , 对于app来说 , 很容易做到 , 只要对接口调用的模块稍加封装即可 。
这种方式同样适用于网页应用 , token可以存于localStorage或者sessionStorage里面 , 然后每发ajax请求的时候 , 都把token拿出来放到ajax请求的header里即可 。 不过如果是非接口的请求 , 比如直接通过点击链接请求一个页面这种 , 是无法自动带上token的 。 所以这种方式也仅限于走纯接口的web应用 。
这种方式用在web应用里也有跨域的问题 , 比如应用如果部署在a.com , api服务部署在b.com , 从a.com里面发出ajax请求到b.com , 默认情况下是会报跨域错误的 , 这种问题可以用CORS(跨域资源共享)的方式来快速解决 , 相关细节可去阅读前面给出的CORS文章详细了解 。
这种方式跟cookie-based的方式同样都还有的一个问题就是ticket或者token刷新的问题 。 有的产品里面 , 你肯定不希望用户登录后 , 操作了半个小时 , 结果ticket或者token到了过期时间 , 然后用户又得去重新登录的情况出现 。 这个时候就得考虑ticket或token的自动刷新的问题 , 简单来说 , 可以在验证ticket或token有效之后 , 自动把ticket或token的失效时间延长 , 然后把它再返回给客户端;客户端如果检测到服务器有返回新的ticket或token , 就替换原来的ticket或token 。
4. 安全问题 在web应用里面 , 会话管理的安全性始终是最重要的安全问题 , 这个对用户的影响极大 。
首先从会话管理凭证来说 , 第一种方式的会话凭证仅仅是一个session id , 所以只要这个session id足够随机 , 而不是一个自增的数字id值 , 那么其它人就不可能轻易地冒充别人的session id进行操作;第二种方式的凭证(ticket)以及第三种方式的凭证(token)都是一个在服务端做了数字签名 , 和加密处理的串 , 所以只要密钥不泄露 , 别人也无法轻易地拿到这个串中的有效信息并对它进行篡改 。 总之 , 这三种会话管理方式的凭证本身是比较安全的 。


推荐阅读