前端跨域问题

前言

Q:跨域不是说是浏览器引起的吗?怎么后端配置cors后就不会跨域了
A:您说得对,跨域问题是由浏览器引起的,但后端配置 CORS 头可以告诉浏览器允许哪些跨域请求。浏览器在发起跨域请求时,会发送一个预检请求(preflight request),检查服务器是否允许该请求。如果服务器返回的 CORS 头中包含了正确的设置,浏览器就会允许该跨域请求。
换句话说,后端配置 CORS 头实际上是在告诉浏览器:“我(服务器)允许你(浏览器)从这些特定的域名(或一些其他配置)发起跨域请求。”这样,浏览器就不会再阻止这些跨域请求了。
所以,尽管跨域问题是由浏览器引起的,但通过在后端配置正确的 CORS 头,可以解决跨域问题,使得浏览器不再阻止跨域请求。

正文

有问题就找解决方案,从解决方案找到合适自己项目的:

解决前端跨域问题方案

方案一 CORS:

node代码:


var express = require('express')
var cors = require('cors')
var app = express()

function handleCors(req, res, next) {
  // 允许的请求方法
  res.setHeader(
    'Access-Control-Allow-Headers',
    'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , reqSource,xx'
  )
  // 允许的请求方法
  res.setHeader('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')

  // 允许携带凭据(cookies)
  res.setHeader('Access-Control-Allow-Credentials', true)

  // 从请求头中获取 Origin 值
  const origin = req.headers.origin
  // 请求包含凭据(如 cookies、HTTP 身份验证或 TLS 客户端证书)时,不能使用通配符 *。
  // 检查请求来源是否允许跨域访问
  if (origin && (origin === 'http://127.0.0.1:8084' || origin === 'http://127.0.0.1:5173')) {
    // 允许特定的来源跨域访问
    res.setHeader('Access-Control-Allow-Origin', origin)
  }

  // 如果是 OPTIONS 请求,直接返回,不进入下一个中间件
  if (req.method === 'OPTIONS') {
    return res.send({ code: 204, err: '' })
  } else {
    next()
  }
}


app.use(handleCors)

// 允许所有源访问
app.use(
  cors({
    credentials: true,
    // // 请求包含凭据(如 cookies、HTTP 身份验证或 TLS 客户端证书)时,不能使用通配符 *。
    origin: 'http://127.0.0.1:5173'
  })
)
// 或者允许特定的来源
// app.use(cors({ origin: 'http://your-frontend-domain.com' }));

// 定义路由和其他中间件
app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from Node.js!' })
})

app.post('/api/info', (req, res) => {
  res.json({ message: 'info from Node.js!' })
})

// 启动服务器
const port = 3000
app.listen(port, () => {
  console.log(`Server is running on port ${port}`)
})

vue代码:

<template>
  <div class="sass_box" @click="handleTestHttp"> sdafsdfasdf </div>
</template>

<script setup lang="ts">
  import axios from 'axios'

  async function handleTestHttp() {
    try {
      // let res = await http.post('/api/info')
      // console.log('res', res)

      axios.defaults.baseURL = 'http://localhost:3000'
      axios.defaults.headers['Content-Type'] = 'application/json'
      axios.defaults.withCredentials = true
      axios
        .get('/api/data')
        .then((res) => {
          // fetch('http://localhost:3000/api/data')
          //   .then((response) => response.json())
          //   .then((data) => {
          console.log(res)
        })
        .catch((error) => {
          console.error('Error:', error)
        })
    } catch (error) {
      console.log('error', error)
    }
  }
</script>

<style lang="scss"></style>

方案二 Nginx反向代理:

前端地址
http://127.0.0.1:5173
后端地址
http://127.0.0.1:3000
Nginx配置

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen  8084;
        server_name 127.0.0.1;
        
        location / {
            proxy_pass  http://127.0.0.1:5173; 
        }
        
        location ~ /api/ {
            # 去掉/api/前缀
            # rewrite ^/api/(.*) /$1 break;
            # 代理到后端服务器
            proxy_pass  http://127.0.0.1:3000; 
        }
    }

}

实际使用前端地址http://127.0.0.1:3000访问,请求后端接口只需添加后端路由,如请求接口http://127.0.0.1:3000/api/info,那么只要fetch(‘/api/info’)
测试nginx配置有没有问题
nginx -t
在这里插入图片描述
编辑器保存时候出现编码问题,后面我使用vscode没出现这个问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方案三 vite.config.ts配置server.proxy:

server: {
      origin: 'http://127.0.0.1:8080',
      proxy: {
        // 字符串简写写法:http://localhost:5173/foo -> http://localhost:4567/foo
        // '/foo': 'http://localhost:4567',
        // 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
        '/api': {
          target: 'http://127.0.0.1:8084', // 后端地址
          changeOrigin: true
          // rewrite: (path) => path.replace(/^\/api/, ''),
        }
      }
    },

前端地址正常访问,请求后端接口只需添加后端路由,如请求接口http://127.0.0.1:3000/api/info,那么只要fetch(‘/api/info’)

方案四谷歌游览器去掉同源策略

在进行前端开发设置谷歌浏览器跨域时遇到了问题,百度上说的方法不管怎么设置就是不能跨域,在死怼中发现了可以这样设置跨域(详见三)
总结三种方法:
一、49版本以前的设置:
  在桌面chrome快捷方式的属性中的目标输入框添加 --disable-web-security 添加部分与前面字符之间有空格(有文章说目标引号结尾的加 --args --disable-web-security,反正我没成功)
在这里插入图片描述二、49版本以后的设置:
  1.在电脑上新建一个目录,例如:C:\MyChromeDevUserData
  2.在属性页面中的目标输入框里加上 --disable-web-security --user-data-dir=C:\MyChromeDevUserData,–user-data-dir的值就是刚才新建的目录(参考上面截图)
三、如果以上两种方法失败,用以下方法
  1.通过桌面快捷方式打开文件位置,找到谷歌浏览器安装位置,看到有个chrome.exe文件
  2.在电脑上新建一个目录,例如:C:\MyChromeDevUserData
  3.打开cmd命令行,进入快捷方式位置 例如 cd C:\Program Files (x86)\Google\Chrome\Application
  4.通过命令行启动谷歌浏览器 C:\Program Files (x86)\Google\Chrome\Application>chrome.exe --disable-web-security --user-data-dir=C:\MyChromeDevUserData (红色部分为启动命令以及跨域设置)
上面第三种方式我觉得和权限有关,非得用命令行启动才生效,但是我做了前面两种方式并以管理员方式启动依然无效。但是每次按第三种操作又麻烦,就偷个懒在桌面写个脚本来启动,脚本内容就是第三种方法的命令,文件命名格式xxx.bat,例如我的:
在这里插入图片描述
在这里插入图片描述
各位根据自己情况做相应更改即可,双击脚本文件即可启动chrome浏览器,并且打开跨域模式
在这里插入图片描述

方案五JSONP

script标签不受同源策略影响,回调函数名需要与后端返回的一直

方案六img

img标签不受同源策略影响,无回调函数

好文推荐

JS中的this详解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值