前端跨域 vue使用代理解决跨域问题

364 阅读4分钟

什么是跨域?

跨域是浏览器的同源策略禁止访问另一个域的资源,

同源

同源策略:same origin policy,如果两个资源(页面)协议,域名,端口都相同,那么就是同源。 即使:两个不同域名指向同一个ip,也算非同源

前端解决跨域的方法

  • jsonp 原理:浏览器在加载script标签的时候可以加载另一个域下的资源,而js标签类似get请求,且返回数据是json格式 使用:
 var script = document.createElement('script') 
 script.style = 'text/javascript' 
 //将要请求的get地址传到script的src属性,并且添加回调函数 script.setAttribute('scr','http://www.domain2.com:8080/login?user=admin&callback=handleCallback') 
 //将script标签放入文档 
 document.head.appendChild(script) 
 //执行回调函数 
 function handleCallback(res){ 
 //处理JSON格式数据 
 alert(JSON.stringify(res)) }

由于请求script只能是get方法,所以JSONP这种方式只能解决get请求,post或者其他http方法无法解决

  • 跨域资源共享 原理:

    • cross-origin -resouce sharing跨域资源共享,允许浏览器向跨源服务器发出http请求,需要浏览器和服务器同时支持
    • 浏览器在发出跨域请求时:1。简单请求,直接在头部信息中带上origin信息,标识属于哪个源,服务端配置access-control-allow-origin接受哪些域名跨域访问,可以是*允许所有
    • 如果是非简单请求会在正式请求之前,发送预检请求
  • 简单来说(简单请求):

    • 是一个双端配合,允许打卡跨域资源限制的一种手段

    • 浏览器端:请求头携带origin信息

    • 服务端:配置access-control-allow-origin允许哪些源跨域

    • 代码:

      • 原生:xmlHttpRequest不需要配置请求头,简单请求会自动带上origin属性
      var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
      
      
          xhr.open('post', 'http://www.domain2.com:8080/login', true);
          xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
          xhr.send('user=admin');
      
          xhr.onreadystatechange = function() {
              if (xhr.readyState == 4 && xhr.status == 200) {
                  alert(xhr.responseText);
              }
          };
      
      • AJAX:有一个属性crossDomain,配置为true之后会让请求头携带orgin跨域额外信息,但是不会自动包含cookie
      $.ajax({
          ...
      xhrFields: {
          withCredentials: true    // 前端设置是否带cookie
      },
      crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
          ...
      });
      
    • VUE中的axios,默认也会把origin放到请求头,不需要额外配置

  • 服务端配置

      /*
       * 导入包:import javax.servlet.http.HttpServletResponse;
       * 接口参数中定义:HttpServletResponse response
       */
    
      // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
      response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
    
      // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
      response.setHeader("Access-Control-Allow-Credentials", "true"); 
    
      // 提示OPTIONS预检时,后端需要设置的两个常用自定义头
      response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
    
  • 反向代理(NodeJs中间件代理跨域)(Vue代理跨域)(nginx转发代理)

  • 场景:当服务器端无法修改cors,并且client全部换成jsonp方式比较繁琐时,只能通过中间代理服务器,将代理服务器设置为支持CORS或者代理服务器和请求页面同源,使页面可以直接请求代理服务器,在通过代理服务器进行接口代理,代理请求目标接口地址,返回数据

  • 原理:跨域限制仅是浏览器端的安全策略,并不是http协议的固有限制,所以中间服务器在参数和cookie有效的情况下是可以正常的请求目标服务器的,Vue(node+webpack+webpack-dev-server)中配置proxy就是启动一个同源的服务进行接口代理

  • 注意:

    • 1.非vue ,webpack,dev-serve服务,单独启的nginx或者node express服务做反向代理时,一般是跟页面非同源,非同源要访问代理服务器也存在跨域问题,需要配置cors允许跨域访问,配置access-control-allow-header
    • 在webpack-dev-server服务,默认应该是基本与测试环境页面同源,不需要配置请求头允许 代码:
  • webpack-dev-server代理

        module.exports = {
        entry: {},
        module: {},
        ...
        devServer: {
            historyApiFallback: true,
            proxy: [{
                context: '/login',
                target: 'http://www.domain2.com:8080',  // 代理跨域目标接口
                changeOrigin: true,
                secure: false,  // 当代理某些https服务报错时用
                cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
            }],
            noInfo: true
        }
    }