uni-app+vue3 来说一说前端遇到跨域的解决方案
前言:
在项目开发中,跨域算是常见的问题了,前端来解决跨域也是有多种方式,比如常见的proxy, uniapp的配置里面也有同样的方法,但是最近我遇到一个很奇怪的问题,不知道是服务端网关限制的原因还是别的原因,就是前端用proxy解决跨域后,接口一直处于pending状态,走不到服务端,所以我使用了nginx来实现跨域解决。这里整理下方法。
跨域问题的产生原因:
指一个页面尝试加载来自跨域(协议、域名、端口)的资源时所遇到的限制和问题,比如:ip/端口不同,产生了跨域问题
小程序与uniapp的内置浏览器无跨域问题:
UniApp 的内置浏览器是基于 WebView 封装的运行环境,默认禁用同源策略
小程序运行在微信/支付宝等平台的沙盒环境中,所有网络请求由客户端原生代码代理,实际请求由平台客户端发出,而非网页浏览器
小程序还有白名单机制:
开发者需在后台配置合法域名(如request 合法域名列表
),平台会自动处理跨域问题,对外表现为"无跨域限制"
特性 | 浏览器 | UniApp 内置浏览器/小程序 |
---|---|---|
请求发起方 | 浏览器 JavaScript 引擎 | 原生 WebView/客户端环境 |
网络栈 | 浏览器网络层 | 原生网络模块(Android/iOS 原生代码) |
同源策略应用 | 严格强制执行 | 默认禁用或由平台代理绕过 |
实际请求地址 | 直接显示目标 URL | 通过客户端代理,隐藏真实端点 |
CORS 检查 | 是 | 否 |
跨域问题前端解决方法:
1、vue项目中使用proxy来解决
新建一个vite.config.js文件
target: // 代理的接口地址
changeOrigin // 是否允许跨域,默认true
secure // 是否校验https的限制
rewrite // 重写地址,
rewrite: path => path.replace(/^\/dev-api/, '') 重写后,路径上没有dev-api,
rewrite: path => path.replace(/^\/dev-api/, 'dev-api') 注释或者这样写,路径上就有dev-api
proxyReq.setHeader // 是可以动态给他在添加请求头,一般不需要
日志打印的:实际转发目标 就是我们代理应该走的实际路径,在编译器或者cmd上看日志
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'export default defineConfig({plugins: [uni()],server: {proxy: {'/dev-api': {target: 'https://cs.he*********', changeOrigin: true,secure: false,rewrite: path => path.replace(/^\/dev-api/, ''), // 可选:重写路径configure: (proxy, options) => {proxy.on('proxyReq', (proxyReq, req) => {proxyReq.setHeader('Host', 'cs.he*******');proxyReq.setHeader('Origin', 'https://cs.he*******');proxyReq.setHeader('Referer', 'https://cs.he*******');console.log('代理请求路径:', req.url, '=>', proxyReq.path) // 检查请求路径console.log('实际转发目标:',`${proxyReq.method} ${proxyReq.protocol}//${proxyReq.getHeader('host')}${proxyReq.path}`)})proxy.on('proxyRes', (proxyRes) => {console.log('实际响应状态码:', proxyRes.statusCode) // 检查响应状态})},}}}
})
2、uniapp中全局配置修改
manifest.json中配置
{"h5": {"devServer": {"proxy": {"/api": {"target": "http://backend-server:8080","changeOrigin": true,"pathRewrite": { "^/api": "" }}}}}
}
3、nginx解决方案:
如果没有安装过nginx,来看这个:点我
传统的nginx请求配置
1、nginx.conf文件常规配置
worker_processes 1;
events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 9005; //你的服务端口server_name localhost; //服务名#下面是与压缩有关的配置,不需要可以不用gzip on; #开启gzip功能gzip_min_length 1024; #响应页面数据上限gzip_buffers 4 16k; #缓存空间大小gzip_http_version 1.1; #http协议版本gzip_comp_level 4; #压缩级别4gzip_types gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php image/jpeg image/gif image/png application/javascript;gzip_vary on; #启用压缩标识gzip_static on; #开启文件预压缩#默认服务,也就是你的localhost:9005 默认展示内容location / {root F:/project/xiruan/framework/; #文件名具体地址index index.html index.htm; #具体文件名}#代理,这里就指向另一个地址了location /dev-api/ {rewrite ^ https://cs.heb************;}}
}
我们这里针对性处理,因为有uniapp需求,所以要加很多东西
proxy_pass 后面是我们的代理地址
add_header 通过这种方法添加请求头
proxy_ssl_verify 是https的校验配置,这里直接关闭
/nginx-1.20.2/logs/api_access.log 这是你的日志放得地方,一个是运行日志,一个是报错日志,直接指向你的盘符地址,比如我这里就是对应的是下面的路径:
location /hx-dev/ {# 处理 OPTIONS 预检请求,post请求严格if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Request-Id,Authorization, X-Requested-With, X-Token, App-Id'; # 添加 uni-app 特有头add_header 'Access-Control-Max-Age' 1728000; # 20天缓存add_header 'Content-Type' 'text/plain; charset=UTF-8';add_header 'Content-Length' 0;return 204;}# 解决跨域的核心配置add_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Content-Type, X-Request-Id, Authorization, X-Requested-With, X-Token, App-Id' always;add_header 'Access-Control-Allow-Credentials' 'true' always;# 代理配置proxy_pass https://cs.h**************/; #代理的地址,后面可以拼接 /abc这种,根据你需求来proxy_set_header Host cs.h*******; #代理的hostproxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# 处理 uni-app 特有头proxy_set_header X-Token $http_x_token;proxy_set_header App-Id $http_app_id;# 日志记录access_log /nginx-1.20.2/logs/api_access.log;error_log /nginx-1.20.2/logs/api_error.log;# HTTPS 相关配置proxy_ssl_verify off;proxy_ssl_server_name on;}
4、node配置请求头方法
app.js中添加跨域请求头
//后端添加请求头解决跨域
app.all('*', function (req, res, next){res.header("Access-Control-Allow-Origin", "*");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");res.header("Access-Control-Allow-Credentials", true);res.header("X-Powered-By", ' 3.2.1');next();
})