1.环境配置
前端:jsp
后端:
Spring MVC
接口一地址:http://localhost:7777
接口二地址:http://localhost:8888
2.案例
1.全局默认请求 http://localhost:7777,也就是Request Headers 的 Origin 属性值为:http://localhost:7777,现需要请求:http://localhost:8888。
test() {
$.ajax({
type: 'get',
url: "http://localhost:8888/test",
success: function(result) {
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
}
});
}
这个请求发出去后,Request Headers 大概如下:
host localhost:7777
origin http://localhost:8888
sec-ch-ua "Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"
这样发送到后端,后端又没做跨域处理的话,会报错:has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the ......
这是因为CORS是一种安全机制,用于限制从一个源加载的文档或脚本如何与另一个源的资源进行交互。当你尝试从一个域名(比如https://example.com
)请求另一个域名(比如https://api.example.com
)的资源时,浏览器会检查服务器返回的Access-Control-Allow-Origin
头是否允许这种跨域请求。
如果服务器没有正确设置这个头,或者它的值不符合请求的源,浏览器就会阻止请求,这就是你看到的“has been blocked by CORS policy”错误。
这时候需要后端做跨域处理,一般设置以下内容即可:
# 声明 CrossFilter 类实现 Filter 并且注入该类使其生效
public class CrossFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
// 允许该域发起跨域请求
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");//*允许任何域
// 允许的外域请求方式
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type,"
+ " X-E4M-With,appId,token,userId");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
2.在上一个基础上,如果需要携带 cookie,有可能后端会使用 cookie 做一些操作,比如获取当前用户信息什么的。
前端 ajax 需要加上参数:
test() {
$.ajax({
// 跨域携带 cookie
xhrFields: {
withCredentials: true
},
type: 'get',
url: "http://localhost:8888/test"
success: function(result) {
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
}
});
}
后端改造如下:
public class CrossFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
// 获取请求域默认*,这里取到的是 http://localhost:7777
String origin = StringUtils.isNotBlank(httpServletRequest.getHeader("Origin")) ? httpServletRequest.getHeader("Origin") : "*" ;
// 允许该域发起跨域请求
httpServletResponse.setHeader("Access-Control-Allow-Origin", origin);//允许任何域,这里不能设置为 *
// 允许的外域请求方式
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
// 是否携带cookie
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type,"
+ " X-E4M-With,appId,token,userId");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
注:以上后端设置还可以声明在控制器里,只针对某个接口:
@RequestMapping(value = {"/test"}, method = {RequestMethod.GET})
public Object getOrgTree(HttpServletRequest request, HttpServletResponse response) {
String origin = StringUtils.isNotBlank(request.getHeader("Origin")) ? request.getHeader("Origin") : "*";
response.setHeader("Access-Control-Allow-Origin", origin); // 星号表示所有的域都可以接受
response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
response.setHeader("Access-Control-Allow-Credentials", "true");
// 业务逻辑
......
}
还有其他解决方案,我就是怎么舒服怎么来。