Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP专题 - Cookie 及 session 的实现 #36

Open
kangschampagne opened this issue Apr 20, 2018 · 0 comments
Open

HTTP专题 - Cookie 及 session 的实现 #36

kangschampagne opened this issue Apr 20, 2018 · 0 comments

Comments

@kangschampagne
Copy link
Owner

@kangschampagne kangschampagne commented Apr 20, 2018

定义

Session:是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库或者文件中。

Cookie:是在客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现 Session 的一种方式。

栗子

除了定义之外,我们更需要熟悉其真正应用的地方。

由于 HTTP 协议是无状态的协议,为了识别具体的用户,就必须在服务端使用某种机制记录用户的状态,而这个机制就是 Session。

比如最常见的购物车场景,当用户点击确认订单的时候,HTTP无状态,所以并不知道是哪个用户提交了订单,这个时候服务端如果为特定的用户创建特定的 Session 作为标识符号,并使用它跟踪用户,那么就可以明确是哪个用户的操作了。

  • 那么服务端如何保存这个 Session 呢?
    一般有内存,数据库或者文件。集群的方式是因为需要 Session 的转移,即当业务复杂需要有 Session 的服务集群,用来保存当前的会话。一般会将 Session 信息放在内存,使用缓存服务器 Memcached 之类的存放 Session。

  • 那么服务端如何识别这是某个客户呢?
    我们知道客户端有 Cookie,每次 Http 请求的时候,客户端都会携带相应 Cookie 的信息到服务器中。那么方法就来了,第一次创建 Session 的时候,服务端会在 HTTP 协议中携带 Session(即在返回头中有 setCookie),这个时候浏览器就会将 SessionName -> SessionId 存入 Cookie 中;之后的请求,只要客户端携带这个 SessionID 就能识别是某个用户了。

  • 客户端如果禁止掉 Cookie 呢,那怎么识别?
    一般这种情况下,都会使用 URL 重写技术进行会话跟踪,即在 URL 上附加 SessionID,每次发起 http 请求的时候,URL 后面都会附加一个 sid=xxx 的参数识别用户。

本来 Session 是一个抽象的概念,开发者为了实现中断和继续等操作,将 user agent 和 server 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是session的概念。
而我们今天常说的 “session”,是为了绕开 cookie 的各种限制,通常借助 cookie 本身和后端存储实现的,一种更高级的会话状态实现。

具体到实现,session 因为 session id 的存在,通常要借助 cookie 实现,但这并非必要,只能说是通用性较好的一种实现方案。

上面我们了解了 Session 和 Cookie 的常用用法,接下来我们深入了解其具体的使用方法。

Cookie

当服务器收到HTTP请求时,服务器可以在响应头里面添加一个Set-Cookie选项。浏览器收到响应后通常会保存下Cookie,之后对该服务器每一次请求中都通过Cookie请求头部将Cookie信息发送给服务器。另外,Cookie的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

Set-Cookie: <cookie名>=<cookie值>

如第一次请求服务器返回:

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: test_cookie=kagen

那么浏览器之后每次请求都会附带:

Host: www.xxx.com
Cookie: test_cookie=kagen

用法就明白了吧,接下来就是关于 Cookie 需要注意的地方了:

  1. 有效期
    会话期 Cookie: 浏览器关闭之后就会删除,所以不需要指定过期时间(Expires)或者有效期(Max-Age)。
    持久性 Cookie: 指定一个过期时间和有效期,时间点是相对于客户端时间的。

  2. 安全
    为了避免XSS攻击,带有 HttpOnly 标记的 Cookie 无法通过 document.cookie API访问。如果服务器返回的 Session 不被 js 读取,那么就应该携带 HttpOnly 标记。
    Set-Cookie: test_cookie=kagen; HttpOnly

  3. 作用域
    可以通过 DomainPath 定义 Cookie 的作用域。
    Domain:不设定一般指向 document.location 对象的 origin。
    只有除了一级域名不同的跨域,可以通过设定 domain 为一级域名实现跨域。如 Domain=xxx.com,则Cookie也包含在子域名中(如developer.xxx.com)
    Path:制定主机下哪些路径可以接受 Cookie,路径必须存在于 请求URL 中。可以通过 字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。

SessionStorage

顾名思义就是 Seesion 的存储,其和 LocalStorage 相同为 本地存储。关于对比,请看笔者的文章。
这里主要提一下 SessinStorage 的几个方面:

  1. 客户端存储
  2. 存储大小为 5 MB 左右
  3. 数据存储的有效期为当前窗口注销之前,只要同源的且同窗口中,刷新页面或者进入同源的不同页面,数据都还存在。主要记住 ”会话“ 的概念,每当创建一个新的标签或者打开一个页面,就会初始化一个新的”会话“。
  4. 不在不同的浏览器窗口中共享,即使是同一页面中的 iframe

其语法也较为简单,方法的返回值是一个 Storage 对象。

// 保存数据到sessionStorage
sessionStorage.setItem('key', 'value')

// 从sessionStorage获取数据
var data = sessionStorage.getItem('key')

// 从sessionStorage删除保存的数据
sessionStorage.removeItem('key')

// 从sessionStorage删除所有保存的数据
sessionStorage.clear()

下面跟随笔者做一个 sessionStorage 的 demo,假如笔者当前写文章的时候不小心按了刷新,那么当前页面文本框的内容可能会丢失,如何使用 sessionStorage 进行保存呢?

// 获取文本框内容
var field = document.getElementById("field")

// 创建文本修改监听,demo
field.addEventListener("change", function () {
  sessionStorage.setItem('textSave', field.value)
})

// 如果突然刷新,取出 storage 中的值
if (sessionStorage.getItem('textSave')) {
  field.value = sessionStorage.getItem('textSave')
}

总结

记清楚 session 的例子,cookie 的注意点,基本上就可以了。

@kangschampagne kangschampagne changed the title HTTP专题 - session 和 Cookie HTTP专题 - Cookie 及 session 的实现 Apr 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.