正文
4)session在一开始并不具备会话管理的作用。它只有在用户登录认证成功之后,并且往sesssion对象里面放入了用户登录成功的凭证,才能用来管理会话。管理会话的逻辑也很简单,只要拿到用户的session对象,看它里面有没有登录成功的凭证,就能判断这个用户是否已经登录。当用户主动退出的时候,会把它的session对象里的登录凭证清掉。所以在用户登录前或退出后或者session对象失效时,肯定都是拿不到需要的登录凭证的。
以上过程可简单使用流程图描述如下:
主流的web开发平台(java,.net,php)都原生支持这种会话管理的方式,而且开发起来很简单,相信大部分后端开发人员在入门的时候都了解并使用过它。它还有一个比较大的优点就是安全性好,因为在浏览器端与服务器端保持会话状态的媒介始终只是一个sessionid串,只要这个串够随机,攻击者就不能轻易冒充他人的sessionid进行操作;除非通过CSRF或http劫持的方式,才有可能冒充别人进行操作;即使冒充成功,也必须被冒充的用户session里面包含有效的登录凭证才行。但是在真正决定用它管理会话之前,也得根据自己的应用情况考虑以下几个问题:
1)这种方式将会话信息存储在web服务器里面,所以在用户同时在线量比较多时,这些会话信息会占据比较多的内存;
2)当应用采用集群部署的时候,会遇到多台web服务器之间如何做session共享的问题。因为session是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建session的服务器,这样他就拿不到之前已经放入到session中的登录凭证之类的信息了;
3)多个应用要共享session时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好cookie跨域的处理。
针对问题1和问题2,我见过的解决方案是采用redis这种中间服务器来管理session的增删改查,一来减轻web服务器的负担,二来解决不同web服务器共享session的问题。针对问题3,由于服务端的session依赖cookie来传递sessionid,所以在实际项目中,只要解决各个项目里面如何实现sessionid的cookie跨域访问即可,这个是可以实现的,就是比较麻烦,前后端有可能都要做处理。
如果不考虑以上三个问题,这种管理方式比较值得使用,尤其是一些小型的web应用。但是一旦应用将来有扩展的必要,那就得谨慎对待前面的三个问题。如果真要在项目中使用这种方式,推荐结合单点登录框架如CAS一起用,这样会使应用的扩展性更强。
2. cookie-based的管理方式
由于前一种方式会增加服务器的负担和架构的复杂性,所以后来就有人想出直接把用户的登录凭证直接存到客户端的方案,当用户登录成功之后,把登录凭证写到cookie里面,并给cookie设置有效期,后续请求直接验证存有登录凭证的cookie是否存在以及凭证是否有效,即可判断用户的登录状态。使用它来实现会话管理的整体流程如下:
1)用户发起登录请求,服务端根据传入的用户密码之类的身份信息,验证用户是否满足登录条件,如果满足,就根据用户信息创建一个登录凭证,这个登录凭证简单来说就是一个对象,最简单的形式可以只包含用户id,凭证创建时间和过期时间三个值。