普歌-多种跨域方式以及解决跨域方案(jsonp、cros、vue中跨域proxy、nginx反向代理跨域)

普歌-跨域及解决跨域(超详细,面试官都夸赞)

前言:了解如何跨域前,首先了解什么是跨域

  1. 同源策略
    - 浏览器的安全策略
    - 协议名、域名、端口号完全一致
  2. 跨域
    违背同源策略就会产生跨域
  3. 解决跨域
    jsonp(前端设置和后端设置) \ cors(后端设置) \服务器代理(后端设置)…

当时3月底面试快手是提起这个怎么解决跨域时,说的面试都称,说的很详细,我相信你即使没实践过也能很快上手(原话)~~~~但最后挂在二面了😂😂😂


在这里插入图片描述

用jsonp解决跨域(前后端配合设置)

jsonp原理是因为script标签是没有同源策略限制,可以跨域的,用动态生成的script标签;限制的话只能发送get请求

封装jsonp函数

    //options中又很多参数
      function jsonp(options) {
        //动态创建script标签
        var script = document.createElement("script"); //拼接字符串的变量
        //进行url参数的拼接,形如name=gl&age=20
        var params = "";
        for (var attr in options.data) {
          params += "&" + attr + "=" + options.data[attr];
        }
        //myJsonp0213212,生成一个函数名(要通过callback传递给后端)
        var fnName = "myJsonp" + Math.random().toString().replace(".", "");
        //我们要想办法将它变成全局函数
        //(变成全局函数的目的在于后端返回的参数形式是->func({data...})前端能自动执行得到真正的参数)
        window[fnName] = options.success;
        //拼接callback以及参数给后端
        //为script标签添加src属性
        script.src = options.url + "?callback=" + fnName + params;
        //将script标签追加到页面中
        document.body.appendChild(script);
        //为script标签添加onload事件,在调用完就移除script,不会增加一些多余的标签
        script.onload = function () {
          document.body.removeChild(script);
        };
      }

进行测试

<body>
     <button id="btn1">点我发送请求</button>     <button id="btn2">
      点我发送请求
    </button>
        
    <script type="text/javascript">
      //获取按钮
      var btn1 = document.getElementById("btn1");
      var btn2 = document.getElementById("btn2"); //为按钮添加点击事件
      btn1.onclick = function () {
        jsonp({
          //请求地址
          url: "http://localhost:3001/better",
          data: {
            name: "lisi",
            age: 30,
          },
          success: function (data) {
            console.log(123);
            console.log(data);
          },
        });
      };
      btn2.onclick = function () {
        jsonp({
          //请求地址
          url: "http://localhost:3001/better",
          success: function (data) {
            console.log(456789);
            console.log(data);
          },
        });
      };

      function jsonp(options) {
        //动态创建script标签
        var script = document.createElement("script"); //拼接字符串的变量
        //
        var params = "";
        for (var attr in options.data) {
          params += "&" + attr + "=" + options.data[attr];
        }
        //myJsonp0213212
        var fnName = "myJsonp" + Math.random().toString().replace(".", "");
        //它已经不是一个全局函数了 
                 //我们要想办法将它变成全局函数
        window[fnName] = options.success;
                //拼接callback以及参数给后端
        //为script标签添加src属性
        script.src = options.url + "?callback=" + fnName + params;
        //将script标签追加到页面中
        document.body.appendChild(script);
        //为script标签添加onload事件,在调用完就移除script,不会增加一些多余的标签
        script.onload = function () {
          document.body.removeChild(script);
        };
      }
    </script>
  </body>

jsonp跨域
我之前也发现百度也使用jsonp发送请求
百度

CROS跨域(CORS是后端的事)

  • 客户端(项目中一般都用axios发送请求)
  • 客户端封装axios
   import axios from "axios";
   import qs from "qs";
   axios.defaults.baseURL = "http://127.0.0.1:3000";
   axios.defaults.timeout = 10000;
     //withCredentials  这个是向服务器跨域发送请求允不允许携带资源凭证(cookie)
   axios.defaults.withCredentials = true;
     /*
      * 设置请求传递数据的格式(看服务器要求什么格式)
      * x-www-form-urlencoded
      */
   axios.defaults.headers["Content-Type"] =
       "application/x-www-form-urlencoded";
   axios.defaults.transformRequest = (data) => qs.stringify(data);
   //以上还可以写成对象形式
 /*  const service = axios.create({
     baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
     timeout: 10000 // request timeout
  })*/
    /*
      * 设置请求拦截器
      * TOKEN校验(JWT):接收服务器返回的token,存储到vuex/本地存储中,每一次向服务器发请求,我们应该把token带上
      */
    axios.interceptors.request.use(
       (config) => {
         let token = localStorage.getItem("token");
         token && (config.headers.Authorization = token);
         return config;
       },
       (error) => {
         return Promise.reject(error);
       }
     );
    /*
      * 响应拦截器
      */
     axios.interceptors.response.use(
       (response) => {
         return response.data;
       },
       (error) => {}
     );
     export default axios;

Node服务端设置跨域

	 //  这里是node中的做法
app.use((req, res, next) => {
   //  允许哪些源访问,到项目中应用的话可以给一个*(就是所有源),或者填写某个具体的域
   res.header("Access-Control-Allow-Origin", "*");
   // 允不允许客户端发送资源凭证 Credentials
   res.header("Access-Control-Allow-Credentials", true);
   // 允许发送哪些请求头
   res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");
   //允许发送哪些请求
   res.header( "Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS,HEAD");
   // 发送正常请求(post/get等)前会提起发送OPTIONS试探性请求,看看能不能连上服务器
   req.method === "OPTIONS"? res.send("CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!"): next();
});

基于http/https proxy实现跨域请求(开发环境)

  • 配置proxy只有在开发环境中起作用,因为webpack只有在开发时用到

  • 第一,配置webpack代理
    打开 webpack 配置文件,进入开发环境下配置。在module.exports的dev对象下。

  • 如果是 vue cli 3 ,刚进入vue.config.js。如果没有vue.config.js文件,在项目的根目录下,创建一个。在module.exports的dev对象下配置,也可以在configureWebpack: config=>{ … } 函数内判断开发环境,然后config.devServer = { 配置信息 }

配置信息如下:

module.exports = {
	devServer: {
	    proxy: {
	    //定义请求的基础URL, 方便跨域请求时使用
	      "/api": {
	      // 目标服务器地址
	        target: "http://172.16.1.18:8769", 
	        // 开启代理服务器,
	        changeOrigin: true,
	         // 将 请求地址前缀 /api 替换为 空的,
	        pathRewrite: {
	          "^/api": ""
	        },
            secure: false
	      }
	    }
	  }
}

参数解读:
“/api”: 指接口调用时,遇到接口路径为 api 时,则代理转发到 target 的配置url上
target: 开发环境调用的接口地址
changeOrigin:改变源到url,在虚拟主机上很有用
pathRewrite:是指服务器把接口中api去掉,以免api这几个字母加入到接口地址中
secure: false, // 接受 运行在 https 上的服务

生产环境中要用nginx反向代理(生产环境)

nginx配置反向代理
/api
配置nginx
还有一个iframe跨域,只不过我没实战过…
iframe跨域
在这里插入图片描述

OVER,get到的小伙伴给个三连呗~~~

更多推荐:wantLG的《普歌-页面优化之实现图片懒加载+节流(面试重点)


  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wantLG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值