问题背景是在一次部署开发环境时,由于是前后端分离项目(前端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 {
@Override
public 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 {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 拦截所有的请求
.allowedOriginPatterns("*") // 使用 allowedOriginPatterns
.allowCredentials(true)
.allowedMethods("*") // 允许跨域的方法,可以单独配置
.allowedHeaders("*"); // 允许跨域的请求头,可以单独配置
}
}
重启 SpringBoot 服务,前端再次访问接口,成功访问,解决跨域问题:
此时响应头如下: