JavaScript 之 跨域

4,016 阅读2分钟

前提

协议相同,域名相同,端口号不同,但是在往cookie存放相同的一个字段token时,会发现 前一个存放的token,会被后一个token 覆盖掉

问题二:同域名下,不同的二级域名清空Cookie导致同域名的Cookie全部清空,如何解决??

之前学习过同源策略,提及到:同一协议、同一域名、统一端口号,当其中一个不满足时,请求会发生跨域问题。

但是在实际项目中,遇到过本地启动两个项目遇到过 “协议相同,域名相同,端口号不同,但是在往cookie存放相同的一个字段token时,会发现 前一个存放的token,会被后一个token 覆盖掉” 这个问题。

本地启动了两个项目,地址分别是

项目A: http://localhost:8001

项目B: http://localhost:8100

两个项目除了端口其他相同,在A、B两个项目中分别设置cookie 中的token,值为1、2,先设置项目A为1,再设置项目B为2,发现几个现象:

  1. 设置项目A中cookie token=1, B项目暂时未设置, 但是可以在项目B中获取token = 1
  2. 设置项目A中 token = 1, 项目B中 token =2 ,在A获取token,发现结果 token = 1

结论

Cookie是不区分端口号的,如果Cookie名相同,会自动覆盖,并且读取是相同的数据。

后续应该想办法避免,例如设置独立的token,或者不同的域名。

另外附有setCookie 和 getCookie

import { Base64 } from 'js-base64';

/**
 * 
 * @param name cookie名称
 * @param value cookie 对应的 value
 * @param time 设置cookie的有效时长
 */
export const setCookie = (name, value, time) => {
  const times = time || 30 * 30 * 48;
  const d = new Date();
  d.setTime(d.getTime() + (times * 60 * 1000));
  document.cookie = `${name}=${Base64.encode(value)};expires=${d.toGMTString()};path=/`;
};

/**
 * 获取cookie
 * @param name
 */
export const getCookie = (name) => {
  const ca = document.cookie.split('; '); // ca格式例如["name=xiaoming", "age=25"]
  let str;
  for (let i = 0; i < ca.length; i += 1) {
    if (name === 'token') {
      if (ca[i].startsWith('token=')) {
        const c = ca[i].split('token=');
        str = Base64.decode(c[1]);
        return str;
      }
    }
    const c = ca[i].split('='); // c格式例如["name", "xiaoming"]
    if (c[0] === name) {
      str = Base64.decode(c[1]);
      return str;
    }
  }
  return str;
};

问题二解决方案:

偶然间注意到cookie的path属性,在set中,设置path属性,实践测试发现,设置这个属性之后,不同的项目虽然域名相同,但是在cookie中不会出现串联的现象,在清空cookie中,也不会出现全部清空的问题。

export const setCookie = (key, value, time) => {
  const cookies = new Cookies();
  const expires =
    time ||
    new Date(
      moment()
        .add(30, 'days')
        .format()
    ); // 过期时间,30天
  cookies.set(key, encrypt(value), {
    path: '/**',
    expires,
  });
};

一、什么是跨域?

当一个请求url的协议、域名、端口三者之间任意一个与当前页面的url不同时即为跨域。

二、解决跨域的方法

1、 通过jsonp 解决跨域

JSONP 是服务器与客户端垮源通信的的常用方法。最大特点就是简单适用,兼容性好,缺点是只能get请求,不支持post请求。

核心思想:网页通过添加一个<script > 元素,向服务器请求JSON 数据,服务器收到请求后,将数据放到一个指定名字的回调函数的参数位置传送回来。

  • 原生实现:
<script src="http://test.com/a.js?callback=dosomething"></script>
<script text="text/javaScript">
  function dosomething (res) {
    console.log(res)
  }
</script>
  • jQuery ajax
$.ajax({
  url: 'http://www.test:8080/login',
  type: 'get',
  dataType: 'jsonp',
  jsonpCallback: 'callBack',
  data: {},
})
  • Vue.js
this.$http.jsonp('http://www.test:8080/login', {
  params: {},
  jsonp: 'callBack',
}).then((res) => {
  console.log(res);
})