浏览器同源策略和跨域问题

其他相关内容:
跨域 - JSONP
跨域 - CORS跨域资源共享

  • 跨域问题只在浏览器中存在,因为在浏览器中才有是否同源的问题。
  • 前端配置代理,通过代理在客户端和服务器之间通信,可以解决跨域问题。

1,同源策略

在浏览器中,同源策略(Same-origin_policy)是一个重要的安全策略。用于限制不同源之间的资源交互。

源的定义:如果两个 URL 的协议端口主机都相同,则这两个 URL 是同源的。

https://blog.csdn.net/pc/index.html 为例:

URL是否同源原因
https://blog.csdn.net/h5/index.html只有路径不同
https://blog.csdn.net/pc/qq/index.html只有路径不同
http://blog.csdn.net/pc/index.html×协议不同
https://blog.csdn.net:8081/pc/index.html×端口不同(https 默认 443)
https://edu.csdn.net/pc/index.html×主机不同

1.1,跨域资源共享CORS

跨域 - CORS跨域资源共享MDN 参考

简单来说,是一种基于 HTTP 头的机制,该机制通过允许服务器指定允许浏览器访问的源来加载自己的资源。

常见的是在服务端接口处添加响应头Access-Control-Allow-Origin来设置允许访问该接口的源。

// 允许任意源访问
ctx.set("Access-Control-Allow-Origin", "*");

2,跨域问题

不同源之间的资源交互,就会存在跨域问题。

最常遇到:请求的接口不同源导致跨域。

2.1,formData 和 form 表单提交

formData mdn参考

  1. 通过 formData 创建的数据,需要发送HTTP请求来提交数据。虽然代码简洁,但可能会跨域
  2. 通过 form 表单提交,不会跨域。

测试代码:

<script setup lang="ts">
import { ref, nextTick } from "vue";
import type { Ref } from "vue";

const sendForm= () => {
  var formData = new FormData();
  formData.append("name", "下雪天的夏风");
  formData.append("want", "求关注");
  var request = new XMLHttpRequest();
  request.open("POST", "http://127.0.0.1:3000/post");
  request.send(formData);
};

const _form = ref() as Ref<HTMLFormElement>;
const formInfo = ref({});
const submitForm= async () => {
  formInfo.value = {
    name: "下雪天的夏风",
    want: "求关注",
  };
  await nextTick();
  _form.value.submit();
};
</script>

<template>
  <button @click="submitForm">form 表单提交</button>
  <button @click="sendForm">formData 发送请求</button>

  <form ref="_form" action="http://127.0.0.1:3000/post" method="post">
    <input v-for="(value, key) in formInfo" :name="key" :value="value" :key="key" type="hidden" />
  </form>
</template>

3,解决跨域

3.1,后端配置响应头

Koa 框架为例,简单示例app.js

这只是简单请求的举例,更详细的内容参考 跨域 - CORS跨域资源共享

const Koa = require("koa");
const Router = require("koa-router");
const { bodyParser } = require("@koa/bodyparser");

const app = new Koa();
const router = new Router();

router.post("/post", (ctx) => {
  //设置响应头允许跨域
  ctx.set("Access-Control-Allow-Origin", "http://localhost:4001");
  ctx.body = {
    code: 1,
    postParams: ctx.request.body,
  };
});

app.use(bodyParser()).use(router.routes());
app.listen(3000);

或对所有请求都配置

// 允许的源
const isAllowedOrigin = (origin) => {
  const allowedOrigins = ['http://localhost:4000', 'http://localhost:5173'];
  return allowedOrigins.includes(origin);
};

router.all("/(.*)", (ctx, next) => {
  const { origin } = ctx.headers;
  if (!isAllowedOrigin(origin)) {
    return;
  }
  ctx.set("Access-Control-Allow-Origin", origin);
  next();
});

前端发送请求

constrequest = new XMLHttpRequest();
request.open("POST", "http://127.0.0.1:3000/post");
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send("foo=bar&lorem=ipsum");

3.2,前端配置代理

本地开发时,前端联调后端接口会使用到代理来解决跨域问题。

1,原理

代理服务器转发客户端(浏览器)的请求到服务端,并将结果返回给客户端

这样,浏览器就不会向服务器直接发起跨域请求了。

2,配置代理举例

webpac 的 webpack-dev-server插件参考

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: '"http://localhost:3000',
        pathRewrite: {'^/api' : ''},
        changeOrigin: true,     // target是域名的话,需要这个参数,
        secure: false,          // 设置支持 https协议的代理
      },
      '/api2': {
          .....
      }
    }
  }
};

vite参考

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:3000",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ""),
      },
    },
  },
});

以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

下雪天的夏风

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

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

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

打赏作者

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

抵扣说明:

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

余额充值