问题背景是在一次部署开发环境时,由于是前后端分离项目(前端Vue3,后端SpringBoot),SpringBoot 使用 Docker 部署,前端访问服务接口时出现跨域问题。
不知道什么是跨域问题的小伙伴可以查看另一篇文章:快速解决Spring Boot跨域困扰:使用CORS实现无缝跨域支持_I’m Jie的博客-CSDN博客
后端服务在现
创建一个最简单的 SpringBoot 项目,在 Controller 中添加一个返回 JSON 数据的接口用于后续前端项目访问,启动项目:
@RestController
public class LoginController {@PostMapping("/login")public User login(@RequestBody User user){return user;}}
前端工程在现
使用 npm init vue@latest
命令创建一个 Vue3 工程,执行 npm install
命令安装依赖,之后使用 npm run dev
命令启动项目,访问 http://127.0.0.1:5173/:
执行 npm install axios
命令安装 Axios
用于访问后端服务的接口,并在 http.js 文件中添加 Axios 对应的配置:
import axios from 'axios'// 创建axios实例
const http = axios.create({baseURL: 'http://127.0.0.1:8080',timeout: 5000
})// axios请求拦截器
http.interceptors.request.use(config => {return config
}, e => Promise.reject(e))// axios响应式拦截器
http.interceptors.response.use(res => res.data, e => {return Promise.reject(e)
})export default http
在 testAPI.js 文件中封装对应的 API:
//封装测试接口函数
import http from '@/utils/http'export const loginApi = ({ account, password }) => {return http({url: '/login',method: 'POST',data: {account:account,password:password}})
}
在 Vue 文件中进行调用:
import http from '@/utils/http'
import { onMounted } from 'vue';//测试接口
onMounted(()=>{http.post('/login', {username: 'Fred',password: 'Flintstone'}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});})
刷新页面,查看开发者工具,发现报跨域问题,原因是我们的前端工程使用的是 127.0.0.1 和 5173 端口,而后端服务使用的是8080端口,所以不可避免出现跨域问题:
Access to XMLHttpRequest at 'http://127.0.0.1:8080/login' from origin 'http://localhost' 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.
访问位于“”的XMLHttpRequesthttp://127.0.0.1:8080/login’来自原点’http://localhost’已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“access control Allow Origin”标头。
此时响应头如下:
解决跨域问题
在后端 SpringBoot 服务中添加配置类解决跨域问题:
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 拦截所有的请求.allowedOrigins("*") // 可跨域的域名,可以为 *.allowCredentials(true).allowedMethods("*") // 允许跨域的方法,可以单独配置.allowedHeaders("*"); // 允许跨域的请求头,可以单独配置}}
但是当前端工程访问时,依然显示跨域问题,查看后端日志输出,找到输出的日志,异常信息如下:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
org.springframework.web.util.NestedServlet异常:请求处理失败;嵌套异常java.lang.IollegalArgumentException:当allowCredentials为true时,allowedOrigins不能包含特殊值“*”,因为该值不能在“Access Control Allow Origin”响应标头上设置。要允许一组来源的凭据,请明确列出它们,或者考虑使用“allowedOriginPatterns”。
重新修改配置类:
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**") // 拦截所有的请求.allowedOriginPatterns("*") // 使用 allowedOriginPatterns.allowCredentials(true).allowedMethods("*") // 允许跨域的方法,可以单独配置.allowedHeaders("*"); // 允许跨域的请求头,可以单独配置}}
重启 SpringBoot 服务,前端再次访问接口,成功访问,解决跨域问题:
此时响应头如下: