HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行管理。
也就是说,无法根据之前的状态进行本次的请求处理。
假设要求登录认证的 Web 页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转新页面不是要再次登录,就是要在每次请求报文中附加参数来管理登录状态
虽然这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。那我们如何实现登录鉴权呢?
常见登录方案
1 基于Cookie的登录鉴权
当我们访问一个网站时,Web服务器会为用户创建一个唯一的会话ID(Session ID),这个ID用于标识该用户在该网站上的访问状态。
什么是Cookie
Server向浏览器发送的一段Token(一段字符串)就是Cookie,而这段token的特殊点在于,浏览器以后每次向同域名的服务器发送请求的时候必须自动带上这段token,只要满足这个特征的token就是Cookie。
如果一个浏览器没有自动的把Cookie带到一个同域名的请求,那这是浏览器的问题
在整个会话期间,浏览器在向同一域名的服务器发送请求都会自动携带Session ID来访问和更新这些数据。当用户关闭浏览器或者会话超时时,该会话将被销毁,相关的数据也将被清除。通过使用会话,Web应用程序可以实现用户认证、状态维护、数据交互等功能。
面试八股之:Session、LocalStorage、SessionStorage、Cookie之间的区别?
- Cookie和LocalStorage的区别:
(cookie是很早就出了,LocalStorage是在h5才出的)
1 Cookie会被浏览器自动发送到服务器,给服务器用于识别状态,而LocalStorage不会,LocalStorage是存给浏览器用的
2 Cookie一般最大4K,LocalStorage可以用5Mb甚至10Mb(各浏览器不同)且前端一般不操作cookie
- SessionStorage和LocalStorage的区别:
1 LocalStorage一般不会自动过期 (除非用户手动清除)
2 SessionStorage在会话结束时过期(如关闭浏览器之后,具体由浏览器自行决定,我当时以为Cookie就存在这里,但不是的)
Cookie和Session
1 Cookie存在浏览器的文件里,Session存在服务器的文件里(占用资源,JWT就出现了)
2 Session是基于Cookie实现的,具体做法就是把SessionID存在Cookie里
Session Cookie如何工作
- 用户访问 a.com/pageA,并输入密码登录。
- 服务器验证密码无误后,会创建 SessionId,并将它保存起来。
- 服务器端响应这个 HTTP 请求,并通过 Set-Cookie 头信息,将 SessionId 写入 Cookie 中,浏览器将Cookies存在临时内存中
第一次登录完成之后,后续的访问就可以直接用Cookie进行身份验证了
- 用户访问 a.com/pageB 页面时,会自动带上第一次登录时写入的 Cookie。
- 服务器端比对 Cookie 中的 SessionId 和保存在服务器端的 SessionId 是否一致(可能篡改造成CSRF攻击)
- 如果一致,则身份验证成功,访问页面;如果无效,则需要用户重新登录。
但session cookies的问题在于:
- 如果服务器需要对接大量客户端,服务端必须存储所有在线用户的 SessionId.
- 如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。
- 由于 SessionId 存放在 Cookie 中,所以无法避免 CSRF 攻击(解决办法见:前端安全系列(二):如何防止CSRF攻击)
2 基于Token的登录鉴权
服务器这时不保存session 数据了,所有数据都保存在客户端,每次请求都发回服务器,这就是JWT的思路。
什么是JWT?
Json Web Token就是一个加密字符串
JWT的原理
JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名
JWT的数据结构
JWT 算法主要分为 3 个部分:header(头信息),playload(消息体),signature(签名)。
- header 部分指定了该 JWT 使用的签名算法;
- playload 部分用来存放实际需要传递的数据
- signature 部分为 JWT 的签名,主要为了做验证,让 JWT 不能被随意篡改。
如何使用JWT
- 用户访问 a.com/pageA,输入账号密码,并点击登录。
- 服务器端验证账号密码无误,创建 JWT。
- 服务器端将 JWT 返回给客户端,由客户端自由保存sessionStorage或者localStorage
- 再次访问时,带上第一次登录时获取的 JWT(封装在Axios中的Authorization头里面)
- 服务器端解密验证该 JWT ,有效且未被篡改则身份验证成功,无效则踢回重新的登录。
当然JWT也可以储存在 Cookie 里面,会被浏览器自动发送,但是这样不能跨域且Cookie是HTTP的内容,在不是HTTP通信的情况下就没有Cookie,JWT的适用性是更广的,Anyway,更好的做法存到localStorage,然后封装到axios中一起发送
JWT的优缺点
- 服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。
- Token 可以存放在前端任何地方,可以不用保存在 Cookie 中,提升了页面的安全性。
- Token 下发之后,只要在生效时间之内,就一直有效,但是如果服务器端想收回此 Token 的权限,并不容易。
Session和JWT的区别就是前者服务器把uid存到内存,然后把key发送给前端,与把uid放到密文,然后把密文发送给前端的区别
3 SSO单点登录
腾讯的衍生产品 比如微信登录后对于微信开发者工具,腾讯云 都是通过微信扫码直接登录授权
Cookie是不跨域的 所以用它的前提是在同源策略下
JWT是目前最流行的跨域认证解决方案
4 基于OAuth的第三方登录鉴权
一键使用第三方登录方式通常使用QQ登录 微信登录 微博登录
比如在豆瓣网站选择使用QQ登录后,豆瓣网站会发起一个重定向302
跳转到由QQ服务器提供的登录授权页面, QQ授权服务器询问用户是否愿意提供用户留在QQ授权服务器上的信息。
如果允许的话 (只是代表用户允许,但并不代表代表这个第三方开发者是合法的,此处就是豆瓣)
第三方开发者要通过QQ 平台颁发的appid 和 appsecret这两个私密信息,调用授权服务器提供的一个接口地址尝试拉取success token
拿到以后就可以向资源进行getresource进行获取资源,带着token 且 token不过期
参考文章: