Skip to content

Latest commit

 

History

History
136 lines (129 loc) · 6.3 KB

8.md

File metadata and controls

136 lines (129 loc) · 6.3 KB

关于cookie

  • cookie是服务端返回数据的时候通过Set-Cookie的Header设置到浏览器上的内容
  • 浏览器在保存了cookie之后,在下一次同源(协议,域名,端口三者一致)请求的时候,自动带上
  • 结合服务端的session以此实现用户访问和权限验证
  • cookie是键值对,可以设置多个值
  • cookie的属性
    • max-age和expires来控制设置过期的时间
    • Secure只在https的时候才会携带和发送
    • 设置HttpOnly就无法通过document.cookie来访问了
      • 只能由服务端来读取,保证了安全性
      • 如csrf攻击, 在网页中注入脚本或通过url来引导用户给攻击者服务器发送用户信息
      • 攻击者可拿到用户登录状态,利用cookie来访问用户在服务器的数据
      • 禁止重要数据通过js来访问是保证安全非常重要的一步

程序示例

  • test.html

    <script>
        console.log(document.cookie);
    </script>
  • server.js

    const http = require('http');
    const fs = require('fs');
    
    http.createServer((req, res) => {
        console.log('req come: ', req.url);
        if(req.url === '/') {
            const html = fs.readFileSync('test.html', 'utf8');
            // 默认是下面这个writeHead设置,不写也可以
            res.writeHead(200, {
                'Content-Type': 'text/html',
                'Set-Cookie': 'uid=joh'
            });
            res.end(html);
        }
    }).listen(8000, () => {
        console.log('server is running on port 8000');
    });
  • 启动程序:$ node server.js

  • 访问:http://localhost:8000/

  • 打开控制台, 查看Network, 可以看到响应头上有了Set-Cookie字段

  • 查看Application中的Cookie缓存, 发现已经被写入了

  • 同时可以看到Console中已经打印出来了当前的cookie信息:uid=joh

  • 再次刷新浏览器,可以看到在请求头上带上了当前的cookie,如果携带多个cookie, 用分号;进行区分

  • 让cookie设置多个值,可以这样

    res.writeHead(200, {
        'Content-Type': 'text/html',
        'Set-Cookie': ['uid=joh', 'age=10'] // 不同的语言,设置方法不同,这里注意一下
    });
  • 重启服务,通过浏览器检查请求头,可以看到

    Set-Cookie: uid=joh
    Set-Cookie: age=10
    
  • 可见,设置了两次cookie信息, 同样, 浏览器缓存中cookie也被存入了这两个

  • cookie是可以设置时效的

    • 一般没有设置过期时间,浏览器关闭后就没有了
    • 设置'Set-Cookie': ['uid=joh;max-age=1', 'age=10']
    • 这样设置uid只有1s的有效期,过了1s再次刷新浏览器发现请求头上只有age的cookie
    • 没有了uid的信息,因为1s时间很短, 这时已经过期了
    • 同样的,除了用max-age,还可以用expires,两者用法不同
    • max-age是设置多长时间,而expires是在什么时间点过期
    • 所以max-age相对简单一些,expires要计算出那个时间点的时间
    • 两者效果一样
  • 关于cookie的HttpOnly属性

    • 设置'Set-Cookie': ['uid=joh;max-age=1', 'age=10; HttpOnly']
    • 重启服务后刷新,可见Console中只打印了uid=joh, 是没有age=10的
    • HttpOnly会禁止js访问cookie, 服务端可正常读取
  • 关于cookie的域名domain设置

    • 设置访问域,一般来说当前域写了cookie, 其他域是无法访问的
    • 举例: a.com写了cookie, 在b.com中是无法访问这个cookie
    • 对同一个域名,cookie有其限制方案,如二级域名
      const host = req.headers.host;
      // 在a.test.com下写cookie
      if(host === 'a.test.com') {
          const html = fs.readFileSync('test.html', 'utf8');
          res.writeHead(200, {
              'Content-Type': 'text/html',
              'Set-Cookie': ['uid=joh', 'age=10']
          });
          res.end(html);
      }
    • 此时,在a.test.com中可以看到写入了cookie, 但是在b.test.com中无法看到任何相关cookie
    • 也就是说我们不能跨域设置cookie, 不能同级或跨级设置,例如:
      const host = req.headers.host;
      // 在a.test.com下写cookie
      if(host === 'a.test.com') {
          const html = fs.readFileSync('test.html', 'utf8');
          res.writeHead(200, {
              'Content-Type': 'text/html',
              'Set-Cookie': ['uid=joh', 'age=10; domain=test.com']
          });
          res.end(html);
      }
    • 上面这个例子是不可以的,无法生效!但是我们可以从高级向低级设置cookie
    • 例如:如果我们想在一级域名test.com中设置cookie, 让二级域名a.test.com来访问则是可以了
      const host = req.headers.host;
      // 在a.test.com下写cookie
      if(host === 'test.com') {
          const html = fs.readFileSync('test.html', 'utf8');
          res.writeHead(200, {
              'Content-Type': 'text/html',
              'Set-Cookie': ['uid=joh', 'age=10; domain=test.com']
          });
          res.end(html);
      }
    • 这样在test.com中查看Cookies, 可以看到设置了cookie, 其Domain是.test.com,其任何二级域名都可以共享cookie
    • 这样的设置,在a.test.com是能够访问到test.com中的cookie的,而且不会被写入任何cookie信息
    • 这就是在二级域名下共享cookie信息,当然也有其他方式来做, 这是最简单的一种方式
    • 小扩展:在Chrome浏览器下可以使用HostAdmin App应用工具来映射域名
  • 关于session的应用

    • cookie与session是两码事,不能混为一谈
    • session有很多种实现方法,不一定会用到cookie
    • 在网站开发中,用到最多的是用cookie来保存session
      • 用户登录后把用户id或其对应的session的key来存入cookie里面
        • 一般会把用户id加密转换成一个key
        • 对应关系会存储在数据库或其他缓存中
      • 下次用户请求后,服务端读取cookie里对应的key值
      • 通过这个key定位用户信息,以此来获得一些操作的权限
    • 其实session的应用不一定用cookie来实现,可以通过js写入请求头中也可以实现,缓存的话可以使用其他形式存储