昨天把vue前端打包到服务器上去发布,但是发布后出现了很奇怪的问题,每个接口都会被请求两次
原来是因为前端跨域访问后端,前端需要先发一个预检请求(不会携带数据)问问后端给不给访问,如果后端返回允许,前端才会发送真正的请求(携带真正的请求数据)
后端处理第一个预检请求:
if (request.getMethod().equals("OPTIONS")) { // 跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。 // 另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求), // 浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request), // 从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。 // 在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。 // 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS response.setStatus(HttpServletResponse.SC_OK); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Allow-Headers", "Authorization,Content-Type"); return; }
Authorization 是一个用户自定义的请求头,类似这种用户自定义的请求头一定要加,否则第二个请求携带这些数据过来的时候会被当成不合法的请求
第二个请求如果登录验证失败了,也需要处理
/* 未登录或token失效 401 */ if (!TokenUtils.verify(request)) { response.setStatus(401); response.setStatus(HttpServletResponse.SC_OK); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "*"); response.setHeader("Access-Control-Allow-Headers", "Authorization,Content-Type"); return; }
解决方案参考:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
其实我们公司的项目没必要废这么些个劲搞跨域,直接dist静态资源放到后端资源路径里就完事了
但是由于开发的时候需要使用代理,所以前端做了一个小小的修改(不使用代理、不使用跨域,感觉页面访问的速度刷刷的,快很多)
生产环境不需要配置代理标识路径,开发环境的时候才设置这个代理匹配的路径
api.service.js
Vue.use(VueAxios, axios); if (process.env.NODE_ENV === "production") { Vue.axios.defaults.basexURL = "" } else { Vue.axios.defaults.baseURL = "/api"; }
vue.config.js
devServer: { host: "0.0.0.0", port: 80, open: false, proxy: { '/api': { target: 'http://localhost:81', changeOrigin: true, ws: true, pathRewrite: { '^/api': '' } }