Talk is cheap

Session/Cookie/JWT与登录验证

在各种的Web/ App项目中,始终绕不过的一个问题就是登录状态保持问题,尤其是在使用Vue前后端完全分离开发时更是头疼这些问题。这里就结合自己的理解做个梳理,总结一下自己以前迷茫的地方。由于其他网站上各种Session /Cookie 的科普文章都已经非常多,这只总结一下这些文章遗漏的地方,或者说是在阅读这些文章时需要具备的一些基础知识。如果不了解这些知识背景,很多很精辟的总结也是看不懂的。就像是学习外语,如果不懂得这门语言的文化,那么就只能是一个翻译器,虽然听得懂,但却总是不能够明白别人的“言下之意”。

1. Http是无状态的


刚接触这个概念的时候,很费解这个概念。来看下面两个场景:

a. 你要跟朋友打电话。那么这个过程会是这样:你拿起电话,开始拨号,等待对方拿起电话,当对方拿起电话的时候,你能听到电话里的盲音消失了,这时候你意识到电话已经接通了。 接下来你要说“Hello”来提示对方,你已经做好了交谈的准备,然后对方也要回复一个 “喂” 告诉你,他也已经做好了通话的准备,大家可以交谈了。

b. 在逛街的时候,路边有个流浪歌手在卖唱。周围围了一群人,路过的人都可以听到流浪歌手的歌声

那么对于以上两个场景:

a就是有状态的,因为通电话的两个人要确认对方已经接通,而且知道对方的身份。然后保持通话。

b就是无状态,只要你路过都能听到歌声,流浪歌手也不会去询问你的身份后才给你听。

2.如何在无状态的Http协议中保存用户状态


搞清楚了什么是无状态,再来看看如何在Http协议中解决用户登录的问题。假设这样的一个情况:有一个网站,刚开始所有的页面都是可以免费浏览,但是后来用户量太大,要做登录控制,让一部分内容在登录后才可以浏览。

如果有过开发一些web开发的话,你很容易想到这样解决:可以在验证了用户名和密码之后,生成一个类似ID的东西(也可以是包含一些信息的字符串),所有限制登录的页面Url都必须带上这个ID,的确,这是一个解决方案,在用户禁止Cookie的情况,这种Url重写的方式能够解决登录状态保持的需求,但是缺点也是明显的: GET方式的Url参数有长度限制,而且比较麻烦。

在web技术的发展过程中,技术人员选择的是使用:Cookie

3.什么是Cookie,什么是Session


网景公司当时一名员工Lou Montulli,在1994年将“cookies”的概念应用于网络通信,用来解决用户网上购物的购物车历史记录,目前所有浏览器都支持cookies。

接着上面的案例来说,在有Cookie的情况下,验证完用户的账号和密码后,服务器可以选择生成一个ID(也可以是包含一些信息的字符串),然后把这个ID存放在返回信息 header里的Cookie属性里,浏览器读取到服务器返回的信息后,检查这个头里如果有cookie信息,就会把Cookie信息保存到本地的浏览器。 这就是Cookie。

从上面的过程中也大概可以发现cookie的这些特点:
a. 服务器/ 浏览器都可以产生Cookie(其本质就是Http通信协议头的一部分),但浏览器负责存储cookie

b. 本地存的cookie,每次都会加在header中,传递给服务器

c. 同域原则: 服务器只能读取本站点的cookie,不能读取其他站点的Cookie

那么什么是Session呢?

Session 翻译为会话,我觉得比较好。就像上文中打电话的例子,如果两个人通话过程中有一个人突然长时间不说话了, 那么我们肯定会觉得对方不在了,然后我们也会把电话挂掉,Session就是这样: 当用户访问一个网站时,服务器可以产生一个Session,以后用户每次浏览网站的其他页面时,服务器都会刷新一下Session的有效期,如果用户浏览该站其他网页的时间间隔很久(也就是Session的有效期)时,服务器就认为客户推出登录了,就相当于打电话时,有一方很久不说话,另一方就会认为对方不在了,至于说这个“很久”有多久,那就完全看你个人的耐心了,如果你认为电话费比较贵,那么超过1分钟就挂了,当然如果你是土豪,又有时间,等一个小时也没问题。
服务器也是如此,不同的服务器等待的时间也是不同的,Tomcat默认等待的时间好像是20分钟。超过这个时间服务器就认为你断线了, 当然如果你直接关闭浏览器,那么就相当于你直接挂掉了电话,服务业任务你已经断线/ 推出登录了
这里涉及一个隐藏的点: Session也是依赖Cookie的,服务器产生一个session,然后也是把这个session的Id放在返回报文的Header头里, 到了浏览器这里,浏览器读取这个SessionID,然后保存在cookie里,以后的每次请求头里都会带上这个sessionID 如下图:

4.如何通过Session/Cookie来进行登录认证。


- 使用Session来验证登录

1. 验证用户输入的用户名密码

2. 验证正确,则在session中放入相关信息

3. 每个页面检查session

这种方法的缺点也很明显,session在服务器端产生,如果用户量很大,那么服务器就有用一部分内存来维持session。 而且Session的本质与Cookie一样,如果用户本地禁用cookie或者原生app开发时,不支持Cookie,那这种方法就没用了。
- 使用Cookie验证登录

1. 验证用户输入的用户名密码

2. 验证正确,则在cookie中放入相关信息

3. 每个页面检查cookie

这个确定同上,如果客户端禁止用cookie,那就完蛋了。

5. Json Web Token 进行登录认证

这种方式的兴起,也是源于移动端的兴起。在使用原生开发APP时,移动端对cookie的支持是不好的,当然使用混合开发的时候,一般不用担心这个问题了,一般框架都有良好的解决方案。
而且原生移动app开发,也涉及跨域的问题,如何进行登录验证与状态保持,就成了实实在在的要解决了问题了,于是就有了token这种方法。

个人理解token 认证这种方式,跟cookie认证比较相似:

 1. 服务器验证用户密码,然后通过ajax返回token 

2. 浏览器 :接到这个token可以存放在在cookie中,以后所有的请求就自动都带着这个token去验证了

   原生App :接到这个token后,由于不支持cookie,可以存放在sqlite数据库中,然后自己定义一个HttpClient类,使用这个类交互数据的时候,会自动把token加入到请求的Http头中。这样就能够很好的解决跨域与 cookie无效的问题`

至于JWT 是一套已经标准化了的 token实施方案,至于如何生成token,如何验证token,网上就又有大把的文章了

未经允许不得转载:CheapTalk » Session/Cookie/JWT与登录验证
分享到: 更多 (0)