JavaScript Cookie

1.简介

  • 参考:cookie by 阮一峰

  • 含义:Cookie 是服务器保存在浏览器的一小段文本信息,一般大小不能超过4KB,浏览器每次向服务器发出请求,就会自动附上这段信息

  • 目的:HTTP 协议不带有状态,有些请求需要区分状态,就通过 Cookie 附带字符串,让服务器返回不一样的回应,例如保存登录状态、购物车等需要记录的信息

2.结构

  • Cookie 数据是以键值对的形式存在的,且每个键值对都有过期时间,每个cookie项有几个部分组成:
属性 含义 说明
Name 名称 名称
Value
Expires 到期时间 默认持续到浏览器关闭
Domain 当前cookie项所属的域名
Path 路径 当前cookie项所属的域名路径,默认是当前路径
HttpOnly 只能由服务端设置 指定该 Cookie 无法通过 JavaScript 脚本拿到,只能由服务端设置
Secure 安全加密 指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器

3.前端操作

  • 设置Cookie:当为cookie项设置其他属性时,用";"进行分隔
// 设置cookie
document.cookie = "username=orochiz"
  • 设置过期时间:各个属性之间用";"进行分隔,时间格式为时间对象
// 添加过期时间(单位:天)
var d = new Date() // 当前时间
var days = 3       // 3天
d.setDate(d.getDate() + days)
document.cookie = "username=orochiz;"+"expires="+d
  • 删除cookie项:设置一个过期的时间,浏览器会自动删除这cookie
var d = new Date() // 当前时间
//过期时间为昨天
d.setDate(d.getDate() - 1)
document.cookie = "username=orochiz;"+"expires="+d
  • 获取Cookie:只能获取名称和值,其他属性拿不到,每个cookie项通过";"进行分隔
// 读取cookie
var msg = document.cookie
console.log(msg) // username=orochiz; age=20
  • 封装操作cookie的函数
// 设置cookie的函数 (过期时间以 天 为单位)
    function setCookie(key,val,days){
        // 获取当前时间
        var d = new Date()
        // getDate()返回月份的某一天 setDate()设置一个月的某一天
        // 将当前时间设置为3天后
        d.setDate(d.getDate() + days)
        // 设置cookie
        document.cookie = `${key}=${val};expires=${d}`
    }

// 获取cookie的函数
    function getCookie(cname){
        // 将cookie字符串分割成数组
        var arr = document.cookie.split(";")
        var name = cname + "="
        // 遍历所有的键值对,查找目标键值对
        for(var i=0;i<arr.length;i++){
            if(arr[i].startsWith(name)){
                return arr[i].substring(name.length)
            }
        }
        // 没有相关的cookie则返回null
        return null
    }

4.服务端操作

  • 设置cookie:在响应头中进行设置
const http = require('http');
 
http.createServer((req, res) => {
  // 设置Cookie
  res.setHeader('Set-Cookie', 'mycookie=test2; path=/; HttpOnly');
  res.end('Cookie set');
}).listen(8097);

5.特性

  • Cookie 有数量和大小的限制,请保证大小不能超过4KB,单个域名设置的 Cookie 不应超过30个
  • Cookie 遵守同源策略,只要域名相同和端口相同,就可以共享 Cookie(不要求协议相同,然而,在浏览器的实际实现中,Cookie并不区分端口)
  • 设置Domain时,默认为当前域名的一级域名,不得设置除当前域名或者其父域名之外的其他domain,访问时也如此
  • 浏览器可以设置不接受 Cookie,也可以设置不向服务器发送 Cookie(详情设置请自主搜索)
// 浏览器是否打开 Cookie 功能
window.navigator.cookieEnabled // true
  • ajax跨域访问:在ajax跨域访问时,默认不会携带cookie,如果需要携带,需要客户端和服务端(cookie所在服务器)同时进行配置,少了一方都不行
//服务端设置(cookie所在服务器)
//express
//要发送Cookie,Access-Control-Allow-Origin就不能设为星号
res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:8090'); // http://127.0.0.1:8090/ 端口号后面不能加 /
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST');
res.header('Access-Control-Allow-Credentials','true');
//浏览器端
axios({
    url:'http://192.168.1.197:8090/test.json',
    withCredentials: true
})

6.CSRF攻击

  • 含义:CSRF(Cross Site Request Forgery,跨站域请求伪造),也被称为 “One Click Attack” 或者 Session Riding,通常缩写为 CSRF 或者 XSRF
  • 原理:一个正常的请求,需要满足3个条件才能执行:接口地址,参数格式,用户登陆状态(cookie),攻击者收集到目标的接口地址和参数格式后,恶意发起对目标网站A的请求,通常情况下,没有A网站的cookie会请求失败,如果此时用户登陆过了A网站,那么此次请求将自动携带A网站的cookie,导致请求成功
1.用户登陆A网站成功,下发A网站cookie
2.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B
3.接着访问B网站,B网站执行新的请求指向A网站
4.因为cookie的特性,这条指向A网站的请求会自动携带A网站的cookie,A网站收到请求后,发现接口地址,参数,cookie都对的上,判定为请求成功
  • GET型攻击:B网站自动开启新页面,访问 "http://a.com?id=1&email=123@163.com" ,因为用户登陆过A网站,请求中携带了cookie,因为被A网站判定为请求成功,用户id为1的邮箱被修改
  • POST型攻击:B网站页面内置一个表单自动进行提交,接口地址 "http://a.com/buygoods/10086" ,此请求自动携带A网站cookie,因为被A网站判定为请求成功,视当前用户购买了该10086代号对应的商品,导致扣款
<form action="http://a.com/buygoods" method="post">
     <input type="text" name="goods" value="10086" />
</form>

<script> 
    //自动提交表单
    document.forms[0].submit()
</script>
  • 防御手段1:验证 HTTP Referer 字段,通过验证请求是否来自同一个服务器,避免跨站攻击,优点是简单易行,判断请求的Referer 的值即可,缺点是Referer 值可能被篡改(旧浏览器存在漏洞),还有可能拿不到Referer 值,导致正常的请求会被认为是CSRF攻击(因为隐私问题,用户自己可以设置浏览器使其在发送请求时不再提供 Referer),导致误判
  • 防御手段2:验证码,通过验证码,强制用户参与此次用户,避免后台自动提交请求
  • 防御手段3:添加 token 并验证,登陆成功后,后台将token下放到前端(前端放到内存中),前端每次请求时携带这个token,后台拿着这个token进行核对,这种方法的难点在于如何把 token 以参数的形式加入请求
posted @ 2024-03-22 10:32  ---空白---  阅读(9)  评论(0编辑  收藏  举报