您的位置:首页 > 运维架构 > 网站架构

关闭浏览器再打开,网站是否应该自动登录以及如何实现呢?

2017-12-26 00:50 666 查看
关闭浏览器再打开,或者说重启浏览器后,网站是否应该自动登录以及如何实现呢?
要回答这个问题,首先要了解session和cookie的概念。基本概念先不说了,直接说重点。

Session是一种服务器端的对象,保存在服务器端。 每个session 有一个唯一的session id。 session的超时也是由服务器来控制。比如,在Django的配置中就有一项叫做SESSION_TIMEOUT的用来控制session超时时间。

而Cookie是由客户端进行保存的,其中会保存session id这一项,用以记录服务器端的session. 正因为有此一项,我们在关闭浏览器后再打开浏览器,如果cookie仍然记住了之前的session id,就导致可以自动登录。

那么cookie什么情况下会记住session id,什么情况下又记不住呢?这就要说到2种cookie:内存cookie和硬盘cookie. 
Cookie分为内存Cookie(也可以说是进程中Cookie)和硬盘Cookie。大部分的session机制都使用进程中Cookie来保存session id,关闭浏览器后这个进程自动消失了,因此Cookie和Cookie中的session id也消失了,再次连接到服务器时无法找到原来的session. 所以,在这种情况下,就是需要再次输入密码登录的。但是保存在硬盘中的cookie却不会丢失session id,所以即使关闭浏览器再打开,也是仍能连得上上一次的session,从而可以自动登录。
又比如说,我们可以在登录时选择“下次自动登录”,例如CSDN的“记住我一周”,或者我们的购物车信息可以在切换不同浏览器时依然可用。这时用到的就是硬盘Cookie,此时,session id将长期保存在硬盘上的Cookie中,直到session失效为止。

除了session和cookie,还有一个常见的服务器端配置项,在Django中叫做 SESSION_EXPIRE_AT_BROWSER_CLOSE. 望文生义,看上去将这个配置项设为True,似乎就可以做到“在重启浏览器之后,必须手动输入密码才能登录”了。其实不然。服务器其实并不知道浏览器关闭了没有,所以关闭浏览器时服务器是不会删除session的,也正是这个原因服务器才会设置一个session的失效时间,不然服务器的资源就会被耗尽。所以当session的失效时间到了,服务器便会将相应的session删除。而我们可以在每一次和服务器的交互中,比如REST API请求和应答,都update当前session,比如session.modified = True, 则该session的超时时间会从当前时间点开始重新计算。
有人可能会说,服务器其实有办法知道浏览器关闭了没有。比如,在JS代码中使用window.onclose来监控标签页是否关闭,然后配合 SESSION_EXPIRE_AT_BROWSER_CLOSE = True ,这样就能够在关闭浏览器的时候清除session了。这么做基本能实现目标,但是也有一个较大的问题:因为在一个浏览器中,可能会有多个标签页,它们是属于同一个session的。当一个标签页被关闭后,该session被清除,会导致所有其他标签页都不可用了。这不会是用户希望得到的体验。

回到最初的问题:关闭浏览器再打开,或者说重启浏览器后,网站是否应该自动登录呢?
答:其实目前有许多网站是支持重启浏览器后自动登录的,比如GitHub. 当然也有些是不支持的,比如网银。
如果要在程序中进行控制,该怎么做呢?笔者实验了一些方法,比如设置cookie的过期时间,但似乎没什么用;不过,可以在浏览器中进行控制。
比如,在Chrome的高级设置的Cookie中,有一项叫做“仅将本地数据保留到您退出浏览器为止”,默认是disable的,将其enable即可实现“重启浏览器,不会自动登录”了。Firefox也有类似的设置。但是,设置这个选项也是有很大副作用的,那就是所有网站都无法自动登录了,比如GitHub. 
所以,总结一下,“对于一般网站来说,即使重启浏览器,仍可以自动登录”,这基本是可以接受的。理由有2点:一、许多知名网站就是这么做的(这似乎不是个好理由);二、服务器端对session其实还是有超时时间控制的,常见的为1小时,当然也有数天的。但是,如果想从程序而不是浏览器的角度,比较完美地控制是否自动登录,笔者还没有找到好的办法。

[补充 - 2018/02/24]
今天在Django官网上(How to use sessions)看到这么一段话,值得补充在这里:

Browser-length sessions vs. persistent sessions

You can control whether the session framework uses browser-length sessions vs. persistent sessions with the 
SESSION_EXPIRE_AT_BROWSER_CLOSE
 setting.By default, 
SESSION_EXPIRE_AT_BROWSER_CLOSE
 is set to 
False
, which means session cookies will be stored in users’ browsers for as long as 
SESSION_COOKIE_AGE
. Use this if you don’t want people to have to log in every time they open a browser.If 
SESSION_EXPIRE_AT_BROWSER_CLOSE
 is set to 
True
, Django will use browser-length cookies – cookies that expire as soon as the user closes their browser. Use this if you want people to have to log in every time they open a browser.This setting is a global default and can be overwritten at a per-session level by explicitly calling the 
set_expiry()
method of 
request.session
 as described above in using sessions in views.NoteSome browsers (Chrome, for example) provide settings that allow users to continue browsing sessions after closing and re-opening the browser. In some cases, this can interfere with the
SESSION_EXPIRE_AT_BROWSER_CLOSE
 setting and prevent sessions from expiring on browser close. Please be aware of this while testing Django applications which have the
SESSION_EXPIRE_AT_BROWSER_CLOSE
 setting enabled.简单来讲,就是Django官方认为,只要设置了 SESSION_EXPIRE_AT_BROWSER_CLOSE为True,就应该是使得用户一旦关闭浏览器,cookie就会过期,而当用户下次打开浏览器的时候,他们就需要重新登录了。但是同时,Django官方又提醒说,有一些浏览器(比如Chrome)会有设置允许用户在关闭后再打开浏览器的时候再次浏览老的session,这样的话,就使得 SESSION_EXPIRE_AT_BROWSER_CLOSE失去了意义。经笔者测试,IE11似乎也是和这里描述的Chrome具有一样的行为。这些也验证了本博客原文倒数第二段所描述的浏览器设置的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  session cookie
相关文章推荐