本文将对比讨论cookie-session与JWT
下面这幅图简单地说明了cookie-session机制与JWT机制
基于Cookie的身份验证
基于 Cookie 的身份验证是长期处理用户身份验证的默认的方法。
基于cookie的身份验证是有状态的。这意味着验证的记录或者会话(session)必须同时保存在服务器端和客户端。服务器端需要跟踪记录session并存至数据库,同时前端需要在cookie中保存一个sessionID,作为session的唯一标识符,可看做是session的“身份证”。
举一个栗子,以登录新浪微博为例,当用户来到微博登陆页面,输入用户名和密码之后,点击“登录”后,浏览器将认证信息POST发送给远端的服务器,服务器执行验证逻辑,如果验证通过,则浏览器会跳转到登录用户的微博首页,在登录成功后,服务器如何验证我们对其他受限制页面的访问呢?
因为HTTP协议是无状态的,所以很显然服务器不可能知道我们已经在上一次的HTTP请求中通过了验证。最简单的解决方案就是所有的请求里面都带上用户名和密码,这样虽然可行,但大大加重了服务器的负担(对于每个request都需要到数据库验证),也大大降低了用户体验(每个页面都需要重新输入用户名密码,每个页面都带有登录表单)。既然直接在请求中带上用户名与密码不可行,那么就只有在服务器或客户端保存一些类似的可以代表身份的信息了,所以就有了cookie与session。
cookie
cookie,简而言之就是在客户端(浏览器等)保存一些用户操作的历史信息(当然包括登录信息),并在用户再次访问该站点时浏览器通过HTTP协议将本地cookie内容发送给服务器,从而完成验证,或继续上一步操作。
session
session,会话,简而言之就是在服务器上保存用户操作的历史信息,在用户登录后,服务器存储用户会话的相关信息,并为客户端指定一个访问凭证,如果有客户端凭此凭证发出请求,则在服务端存储的信息中,取出用户相关登录信息,并且使用服务端返回的凭证常存储于Cookie中,也可以改写URL,将id放在url中。这个访问凭证一般来说就是SessionID。
小结
session和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同。
session可以通过cookie来完成,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端。因此cookie存在着一定的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集(例如:1. appA主动设置域B cookie,让域B cookie获取;2. XSS,在appA上通过javascript获取document.cookie,并传递给自己的appB)。
基于cookie-session身份验证机制的流程
1.用户输入登录信息
2.服务器验证登录信息是否正确,如果正确就创建一个session,并把session存入数据库
3.服务器端会向客户端返回带有sessionID的cookie
4.在接下来的请求中,服务器将把sessionID与数据库中的相匹配,如果有效则处理该请求
5.如果用户登出app,session会在客户端和服务器端都被销毁
基于token的身份验证
最近几年由于单页app、web APIs等的兴起,基于token的身份验证开始流行。当我们谈到利用token进行认证,我们一般说的就是利用JSON Web Tokens(JWTs)进行认证。虽然有不同的方式来实现token, 事实上,JWTs 已成为标准。因此在本文中将互换token与JWTs。
基于token的身份验证是无状态的,服务器不需要记录哪些用户已经登录或者哪些JWTs已经处理。每个发送到服务器的请求都会带上一个token,服务器利用这个token检查确认请求的真实性。
这里可以把token理解成一张演唱会的门票。服务器(演唱会主办方)每次只需要检查你这张门票的有效性,不需要知道你这张门票是在哪里买的,从谁买的,什么时候买的等等。不同等级的门票可以坐的位置不同,同样的,权限不同的用户可以进行的操作也不同。
token通常以Bearer { JWT }的形式附加在已验证的请求头中,但是也可以用post请求体或者问句参数进行传递。
JWT
JWT是一种无状态的鉴权机制。将用户登录后的一些信息(比如用户Id)和过期时间等信息存储在一个加密过的字符串中,当服务器收到请求的时候,进行解密并直接使用信息
JWT的组成:使用base64编码描述jwt的头部、使用base64编码的payload,以及加密签名
缺点,服务器无法像session一样方便地管理用户登录状态
JWT机制工作流程
1.用户输入登录信息
2.服务器验证登录信息,如果正确就返回一个已签名的token
3.这个token存储在客户端,最常见的是存储在localstorage中,但是也可以存在session storage和cookie中
4.之后向服务器发送的请求都会带上这个token
5.服务器解码JWT,如果token是有效的则处理这个请求
6.如果用户退出登录,token会在客户端销毁,这一步与服务器无关
参考:
http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/
https://auth0.com/blog/cookies-vs-tokens-definitive-guide/
https://my.oschina.net/biezhi/blog/490242#OSC_h2_3