你真的了解Cookie和Session吗?
第一层楼
什么是Cookie和Session?(初级程序员高频面试题)
什么是Cookie
HTTP Cookie (也叫做Web Cookie或者浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据(存有少量用户数据的字符串),它会在浏览器下一次请求同一个服务器时被携带并发送至服务器端。通常,它用作告知服务器端两次请求是否来自同一个浏览器,如保持用户的登录状态等。由于HTTP协议是无状态协议,因此,Cookie的出现使其记录稳定的状态信息变成了可能。
Cookie主要用于一下三个方面:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其他需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
什么是Session
Session 代表着服务器与客户端的一次会话过程。Session 对象储存特定用户会话所需的属性以及一些配置信息。这样,当用户在应用程序的Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话(关闭浏览器),或者Session超时(为了保证信息安全,Session会设置过期时间,一般为20分钟)失效时会话结束。
第二层楼
Cookie 和 Session 有什么不同
- 作用范围不同,Cookie 保存在客户端(浏览器端),Session 保存在服务器端
- 存取方式不同,Cookie 只能保存ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。(不建议将敏感信息存入 Session 中,以免泄露重要信息)
- 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同,Cookie 存储在客户端,比较容易遭到窃取,早期有人将用户的用户名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
第三层楼
为什么需要 Cookie 和 Session ,他们之间有什么关联?
说到为什么需要 Cookie,要从浏览器开始说起,众所周知,浏览器是没有状态的,确切的说是HTTP协议无状态,这意味着浏览器并不知道是谁在和服务端打交道,试想一下,当我们登录完成后跳转到另一个页面需要再次登录,用户肯定是无法接受的,为了解决诸如此类的问题,就需要有一个机制来告诉服务端,本次操作的用户是否登录,是哪个用户在执行相关操作,因此,Cookie 和 Session 机制应运而生。
那么 Cookie 和 Session 是如何配合的呢?
用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建相应的 Session , 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。
当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息页发送给服务器端,服务器端会从 Cookie 中获取 SessionID,再根据 SessionID查找对应的 Session 信息,如果没有找到说明用户没有登录或登录失效,如果找到 Session 证明用户已经登录可执行后面的操作。
根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态的。
第四层楼
既然服务端是根据 Cookie 中的信息判断用户是否登录,那么如果浏览器中禁止了 Cookie,如何保障整个机制的正常运转。
第一种方案,在每次请求中都携带一段 SessionID 的参数,也可以以 POST 的方式提交,也可以在请求的地址后面拼接 xxx?SessionID=xxx。
第二种方案,Token机制。Token机制多用于 APP 客户端和服务器交互的模式,也可以用于 Web端做用户状态管理。
Token 的意思是“令牌”,是服务器端生成的一串字符串,作为客户端进行请求的一个标识。Token机制和 Cookie 和 Session 的使用机制比较类似。
当用户第一次登录后,服务器根据提交的用户信息生成一个 Token,响应时将 Token 返回给客户端,以后客户端只需携带上 Token 来请求数据即可,无需再次进行登录验证。
第五层楼
如何考虑分布式 Session 问题?
在互联网公司为了可以支持更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务器 B 就会出现登录失效的问题。
分布式 Session 一般会有一下几种解决方案:
Nginx ip_hash 策略,服务端使用 Nginx 代理,每次请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建了 Session,第二次被分发到了服务器 B 的现象。
Session 复制,任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其他节点。
共享 Session,服务端无状态化,将用户的 Session 等信息通过缓存中间件统一管理,保障分发到每一个服务器的相应结果都应该一致。
建议此用第三种方案。
第六层楼
如何解决跨域请求? Jsonp 跨域的原理是什么?
说起跨域请求,就必须要了解浏览器的同源策略,同源策略/SOP(Same Origin Policy)是一种约定,由 Netscape(网景)公司 1995 年引入浏览器,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,那么浏览器很容易受到 XSS、CSRF 等攻击。所谓同源是指“协议+域名+端口”三者相同,即使两个不同的域名指向同一个 IP 地址,也非同源。
解决跨域请求的常用方法:
线下开发环境,如果是 Vue/React 等框架,可以通过 WebPack 代理接口转发,实现跨域。
线上生产环境,可以通过 Nginx 在后端转发请求,避免前端出现跨域问题
Jsonp跨域
cors(Corssing-Origin-Sharing)跨域资源共享 的方式进行跨域
其他跨域解决方案
重点谈一下 Jsonp 跨域原理。浏览器的同源策略把跨域请求都禁止了,但是页面中的
<script>
<img>
<iframe>
等标签是例外,不受同源策略的西限制。Jsonp 就是利用<script>
标签跨域特性进行跨域数据访问。Jsonp 的理念是,与服务端约定好一个回调函数名,服务端接收到请求后,将返回一段 JavaScript,在这段 JavaScript 代码中调用约定好的回调函数,并且将数据作为参数进行传递。当网页接收到这段 JavaScript 代码后,就会执行这个回调函数,这时数据已经成功传输到客户端了。
JSONP 的缺点是:它只支持 GET 请求,而不支持 POST 请求等其他类型的 HTTP 请求。