cookie
解决浏览器和服务器的识别问题
:服务器不认识这是同一个用户
HTTP是无连接的,请求完毕之后,链接就断掉了,没有长久的数据通路。
HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。Cookie一定是字符串。
Cookie就是在`下行HTTP响应的报文头中,添加set-cookie属性`,要求浏览器设置cookie.
浏览器每次都会在上行请求的报文头中,携带cookie上去,方法服务器对自己的识别
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据
,它会在浏览器向同一服务器再次发起请求时被携带上
,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)
一唱一和
在php后台设置setcookie(“name”,“Ellie”),浏览器访问后,响应中会有
之后再次访问,请求会带上
login.php
用cookie做用户登录,不安全,因为cookie是明文传输
做登录要用session技术
Cookie做本地存储的问题:
Cookie 曾一度用于客户端数据的存储
需要不断的通过HTTP请求,响应,在浏览器和服务器之间来回穿梭传递,不断Set-Cookie,携带cookie,效率比较低
新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。
cookie,localStorage,sessionStorage,indexDB区别
特性 | cookie | localStorage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4K | 5M | 5M | 无限 |
与服务端通信 | 每次都会携带在 header 中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
从上表可以看到,cookie
已经不建议用于存储。如果没有大量数据存储需求的话,可以使用 localStorage
和 sessionStorage
。对于不怎么改变的数据尽量使用 localStorage
存储,否则可以用 sessionStorage
存储。
- 共享
sessionStorage不能共享,localStorage在同源文档之间共享,cookie在同源且符合path规则的文档之间共享
对于 cookie
,我们还需要注意安全性。
属性 | 作用 |
---|---|
value | 如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识 |
http-only | 不能通过 JS 访问 Cookie,减少 XSS 攻击 |
secure | 只能在协议为 HTTPS 的请求中携带 |
same-site | 规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击 |
- 用途
会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
个性化设置(如用户自定义设置、主题等)
浏览器行为跟踪(如跟踪分析用户行为等) - 创建过程
服务器发送的响应报文包含 Set-Cookie 首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 请求首部字段发送给服务器。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
- 分类
会话期 Cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。
持久性 Cookie:指定过期时间(Expires)或有效期(max-age)之后就成为了持久性的 Cookie。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
- 作用域
Domain 标识指定了哪些主机可以接受Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置Domain=mozilla.org,则 Cookie 也包含在子域名中(如
developer.mozilla.org)。
Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配:
/docs
/docs/Web/
/docs/Web/HTTP
- JavaScript
浏览器通过 document.cookie 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie)
- HttpOnly
标记为 HttpOnly 的 Cookie不能被 JavaScript 脚本调用
。跨站脚本攻击 (XSS) 常常使用 JavaScript 的document.cookie API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
- Secure
标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求
发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 - Chrome 51 开始,浏览器的 Cookie 新增加了一个
SameSite属性
,用来防止 CSRF 攻击和用户追踪。
SameSite属性
可以设置三个值:Strict,Lax,None
- Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。
- Lax
Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。
设置了Strict或Lax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。
- None
Chrome 计划将Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
下面的设置无效。
Set-Cookie: widget_session=abc123; SameSite=None
下面的设置有效。
Set-Cookie: widget_session=abc123; SameSite=None; Secure
Session
session就是密文的cookie,是随机乱码的
浏览器和服务器之间的唯一的识别因素,就是这串乱码。
服务器确实耗费了一定的内存,需要存储每个用户的映射信息。
除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端
,存储在服务器端的信息更加安全。
Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。
使用 Session 维护用户登录状态的过程如下:
- 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
- 服务器验证该用户名和密码,
如果正确则把用户信息存储到 Redis 中
,它在 Redis 中的 Key 称为 Session ID; - 服务器返回的响应报文的
Set-Cookie 首部字段包含了这个 Session ID
,客户端收到响应报文之后将该 Cookie值存入浏览器中; - 客户端之后对同一个服务器
进行请求时会包含该 Cookie 值
,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。
应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 SessionID 值。
此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。
浏览器禁用 Cookie
此时无法使用 Cookie 来保存用户信息,只能使用 Session。除此之外,不能再将 Session ID 存放到 Cookie 中,而是使用 URL 重写技术,将 Session ID 作为 URL 的参数进行传递。
对比
Cookie和Session都是客户端与服务器之间保持状态的解决方案。
具体来说,cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案
Session 与 Cookie 的对比
-
实现机制:Session的实现常常依赖于Cookie机制,通过Cookie机制回传SessionID;
-
大小限制:Cookie有大小限制并且浏览器对每个站点也有cookie的个数限制,Session没有大小限制,理论上只与服务器的内存大小有关;
-
安全性:Cookie存在安全隐患,通过拦截或本地文件找到cookie后可以进行攻击,而Session由于保存在服务器端,相对更加安全;
-
服务器资源消耗:Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力。
Cookie 与 Session 选择
- Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选Session;
- Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密;
- 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。
token
token是一个加密的字符串,里面有个人的身份信息,设备信息等(操作系统版本,浏览器版本,IP地址,用户名,手机号)
服务器掌握信息的算法,浏览器掌握信息本身
token比session差在哪里:
token不能判断用户是谁,只能知道用户是不是合法登陆的
掌握
Cookie 有哪些字段