同源策略、跨域、解决跨域

99 阅读2分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

定义

只有协议、主机、端口号全都相同的情况下,才能称两个URL同源。

URL同源原因
www.baidu.com/test/login.…
www.baidu.com/test/test1/…
www.baidu.com:81/test/share.…端口号不同(默认80)
www.baidu.com/test/share.…协议不同
aaa.baidu.com/test/share.…主机不同

目的

保证用户信息安全,防止恶意的对网站进行数据窃取

限制

在非同源的情况下

  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM 无法获得
  • AJAX 请求不能发送

解决跨域

  • CORS:使用额外的HTTP头来告诉浏览器 让运行在一个 origin 上的 Web 应用被准许访问来自不同源服务器上的指定的资源

    • node

      • 原生

        app.use(async (ctx, next) => {
          ctx.set("Access-Control-Allow-Origin", ctx.headers.origin);
          ctx.set("Access-Control-Allow-Credentials", true);
          ctx.set("Access-Control-Request-Method", "PUT,POST,GET,DELETE,OPTIONS");
          ctx.set(
            "Access-Control-Allow-Headers",
            "Origin, X-Requested-With, Content-Type, Accept, cc"
          );
          if (ctx.method === "OPTIONS") {
            ctx.status = 204;
            return;
          }
          await next();
        });
        
      • 第三方

        const cors = require("koa-cors");
        app.use(cors());
        
  • node正向代理:利用服务端请求不会跨域的特性,让接口和当前站点同域。

    • proxy

      //webpack
      const path = require("path");
      const HtmlWebpackPlugin = require("html-webpack-plugin");
      
      module.exports = {
        entry: {
          index: "./index.js"
        },
        output: {
          filename: "bundle.js",
          path: path.resolve(__dirname, "dist")
        },
        devServer: {
          port: 8000,
          proxy: {
            "/api": {
              target: "http://localhost:8080"
            }
          }
        },
        plugins: [
          new HtmlWebpackPlugin({
            filename: "index.html",
            template: "webpack.html"
          })
        ]
      };
      
      //vue2-->config/index.js
      proxyTable: {
        '/api': {
           target: 'http://localhost:8080',
        }
      },
      
      //vue3-->vue.config.js
      module.exports = {
        devServer: {
          port: 8000,
          proxy: {
            "/api": {
              target: "http://localhost:8080"
            }
          }
        }
      };
      
  • nginx反向代理:保证当前域能获取到静态资源和接口,但不关心是怎么获取的

    //nginx
    server {
            listen 80;
            server_name local.test;
            location /api {
                proxy_pass http://localhost:8080;
            }
            location / {
                proxy_pass http://localhost:8000;
            }
    }
    
  • JSONP:script标签没有跨域限制的特性,仅支持get

<script type="text/javascript">
  window.jsonpCallback = function(res) {
    console.log(res);
  };
</script>
<script
  src="http://localhost:8080/api/jsonp?msg=hello&cb=jsonpCallback"
  type="text/javascript"
></script>
  • window.name:无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它;容量大,但影响性能
  • window.postMessage:跨文档通信 API,为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源