Vue报错has been blocked by CORS policy: Response to preflight request doesn‘t pass access controlcheck
【已解决–我的是由于vue-cli版本问题,前文太长可以直接跳转到解决方案】
全部的报错信息:
Access to XMLHttpRequest at 'http://127.0.0.1:7772/person/sysOrgInfo/query-next-org-emp?id=xxx' from origin 'http://localhost:8086' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
项目中添加了token验证功能,本来可以正常使用加上token认证后就出现报错。刚开始我以为是跨域问题,项目的服务端已经添加了跨域的解决方案,postman测试可以访问,前端去访问接口时会出现报错。
跨域问题产生
:当我们的服务端和前端不在一个服务器或者在同一个服务器但是使用不同的接口时,就会出现跨域问题。跨域问题的出现是由于浏览器的同源策略。
服务端跨域解决
服务端跨域解决:新建一个配置文件,全局跨域问题解决(项目部署上线后,前端的本地代理失效,须采用后端跨域解决方案或者在Nginx配置代理
)我这里下面的解决方案主要针对的是在开发环境下后端已经配置跨域前端还不能进行访问的问题
1.后端相关Controller添加跨域注解@CrossOrigin( 这个注解可以让外界直接访问到这个controller层,但是需要每一个controller都添加 太麻烦)
2.新建CorsConfig类,继承WebMvcConfigurer ,并重写addCorsMappings方法
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 是否允许证书
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT","OPTIONS")
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
一般来说服务端通过CORS配置跨域后,前端不需要再进行额外的配置,这个问题现在我也没弄清楚==后面研究清楚会进行文章的更新。感谢weixin_47694910 提出的问题。
由于这个项目的前端不是我写的,是之前的同事写的(我本身前端做的也很少,vue也是刚接触)网上找了一下前端的axios的跨域解决方案。项目之前是可以使用的,也调用了不同的端口和ip,可以使用,感觉可能不是跨域问题。
在服务端打印前端发送请求时的request是否携带token信息,出现报错的请求的token为null
2021-05-12 10:00:56.159 [http-nio-7772-exec-9] ERROR com.hengan.person.filters.PmsFilter - token:null
使用postman进行测试
返回的结果
使用postman可以成功访问,并且可以确定后端的跨域是没有问题的。所以问题应该是出在前端的处理上。
Nginx配置跨域(下文的解决方案是开发环境下,部署上线需要在nginx中配置反向代理)
在nginx的配置文件下进行配置(nginx.conf)现在将完整的nginx配置放上来。
user root;
#开启大线程数 一般与cpu核数一致
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#根据nginx安装位置不同会出现区别 指定进程id存放位置
pid /etc/nginx/logs/nginx.pid;
events {
#每个进程的最大连接数
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#开启高效文件传输模式
sendfile on;
#tcp_nopush on;
#客户端连接活动的超时时间
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
#虚拟server的配置
server {
#监听端口7776 前端页面的访问端口
listen 7776;
server_name localhost;
#前端代码的位置(vue打包后dist文件在服务器的位置)
root /root/nginx/html/test;
#7773相关的接口
location /api {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
#代理的服务端地址
proxy_pass http://127.0.0.1:7773/;
}
#权限相关的接口
location /pms {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:7771/pms/;
}
# 避免访问出现 404 错误
location / {
try_files $uri $uri/ @router;
index index.html;
}
location @router {
rewrite ^.*$ /index.html last;
}
location = /index.html {
add_header Cache-Control "no-cache, no-store";
}
}
}
前端工程运行在7776端口,后端工程运行在7773端口和7771,后端工程的项目路径是/api和/pms,上面配置的意思是监听7776端口,把/api请求转发到7773端口,把路径中带/pms的都转发到7771端口。这样我们在测试时,前端工程的访问地址是:http://localhost:7776/,而前端工程中所有后台接口的路径都统一写相对路径/api/** 或者 /pms/**。上面配置的是前端同时访问两个服务api 和 pms,pms做权限控制。
前端的跨域配置
首先查看自己是否进行了跨域配置,首先查看vue.config.js
文件,发现module.exports下的proxy并没有进行配置,配置
module.exports = {
// hash 模式下可使用
// publicPath: process.env.NODE_ENV === 'development' ? '/' : './',
publicPath: '/',
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: false,//process.env.NODE_ENV === 'development',
productionSourceMap: false,
devServer: {
port: port,
open: false,//是否自动打开浏览器
overlay: {
warnings: false,
errors: false
},
proxy: {
'/api': {
target: process.env.VUE_APP_BASE_API,
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
},
'/person': {
target: process.env.VUE_APP_BASE_PERSONSYS,
changeOrigin: true,
pathRewrite: {
'^/person': '/'
}
},
'/pms': {
target: process.env.VUE_APP_BASE_AUTHORITY,
changeOrigin: true,
pathRewrite: {
'^/pms': '/'
}
}
}
},
配置完成后进行测试,这里axios写了两种封装的方式,经过测试都可以成功访问
import request from '@/utils/request'
//方式一 路径一定要换成/pms 和你在proxy中配置的必须保持一致,会进行url的替换
export const validateLogin = (data) => {
return request.post( '/pms/pms-user-info/validateLogin', data).then(res => res.data);
}
//用户登录 方式二
// export function validateLogin(data) {
// return request({
// url: '/pms/pms-user-info/validateLogin',
// method: 'post',
// data
// })
// }
// export default { validateLogin }
解决方案
发现还是不行,第一次预请求发送成功,实际的请求还是发送不过去,我以为是后端出了问题,仔细的进行了确认,发现后端没有问题,然后我在vue.config.js
中进行了数据打印测试,发现没有效果,然后尝试在这个文件中进行端口号的修改,发现也没有任何效果,此时确定是vue.config.js
文件不生效所导致。这时我想到在config包下的index.js
进行配置
dev: {
env: require('./dev.env'),
port: process.env.VUE_APP_PORT || 8011,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://127.0.0.1:7772/person',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
},
'/person': {
target: 'http://127.0.0.1:7772/person',
changeOrigin: true,
pathRewrite: {
'^/person': '/'
}
},
'/pms': {
target: 'http://127.0.0.1:7771/pms',
changeOrigin: true,
pathRewrite: {
'^/pms': '/'
}
}
},
发现项目可以成功运行。
查阅资料发现:proxyTable在vue早期的cli2项目中使用,proxy在vue-cli3项目中使用
查看我的项目中使用的vue和vue cli版本信息
Vue版本信息
查看vue版本可以在package.json
输入命令npm list vue
也可以
查看vue cli版本
vue -V
出现问题
解决方法:
1、管理员身份运行PowerShell(命令提示符,来源于Linux的命令提示符也叫Shell)快捷键CTRL + X
选择系统管理员运行
2、执行:set-ExecutionPolicy RemoteSigned (签名或运行这些脚本)
回车输入Y即可。
PS D:\repoSVN\人员管理\person_view> vue -V
2.9.6
由于我的版本是2.x 所以需要在proxyTable进行跨域的配置。
【到这问题以及解决完毕】下面是我在查找资料过程中翻出来的一些解决方案,但是好像不好使。
网上的一些解决方案
一、Content-Type设置为表单类型就不会再报那个CORS跨域错误了
headers设置问题:
headers: {
'Content-Type':'application/x-www-form-urlencoded'
}
二、axios的post传参数要使用Qs序列化
import Qs from 'qs'
Qs.stringify(params)
出现上文的报错也可能不是跨域的问题,确保跨域配置没有问题,可以尝试从其他方向进行思考解决。
最后更新于2021-9-2
正在学习中的小白,如有错误欢迎指点,感谢您的帮助。转载请注明出处,感谢!
更多推荐
所有评论(0)