实际前端F12问题:
Access to XMLHttpRequest at ‘域名1 ‘ from origin ‘域名2‘ 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.
解决方案 :
1、tomcat/conf/web.xml 加上,表示禁用options方法
<security-constraint>
<web-resource-collection>
<http-method>OPTIONS</http-method>
</web-resource-collection>
<auth-constraint></auth-constraint>
</security-constraint>
扩展:
需要禁用的HTTP方法
<security-constraint>
<web-resource-collection>
<web-resource-name>acooly-default-policy</web-resource-name>
<!-- 表示需要认证控制的URL -->
<url-pattern>/*</url-pattern>
<!-- 以下多个是表示允许的http请求方法 -->
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>HEAD</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<!-- 表示:需要认证 -->
<auth-constraint/>
</security-constraint>
允许访问的HTTP方法
<security-constraint>
<web-resource-collection>
<web-resource-name>acooly-default-policy</web-resource-name>
<!-- 表示需要认证控制的URL -->
<url-pattern>/*</url-pattern>
<!--
以下多个是表示允许的http请求方法
注意:实测区分大小写
-->
<http-method-omission>POST</http-method-omission>
<http-method-omission>post</http-method-omission>
<http-method-omission>GET</http-method-omission>
<http-method-omission>get</http-method-omission>
</web-resource-collection>
<!-- 表示:需要认证 -->
<auth-constraint/>
</security-constraint>
其他问题影响:
后端没有设置header
解决办法:后端action(controller)里添加如下代码即可
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
前端设置的数据格式不正确
解决办法:前端ajax里删除contentType
扩展学习Java中可以使用以下方式来解决跨域问题:
1. 通过设置响应头Access-Control-Allow系列,来声明哪些域名可以访问该接口。
例如,在controller中添加如下代码:
@CrossOrigin(origins = "http://example.com")
@RequestMapping("/api")
@RestController
public class ApiController {
@RequestMapping("/user")
public Object getUser() {
// your code here
}
}
也可以通过在Filter中设置响应头,来应用于整个应用程序。
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
}
2. 使用反向代理
将请求发送到同源下的Web服务器,让Web服务器代为转发请求。通常我们会使用Nginx或者Apache来进行反向代理。
例如,在Nginx中加入以下配置:
location / {
proxy_pass http://localhost:8080/;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' '*';
}
3. 使用JSONP
JSONP是一种实现跨域访问的方式。它利用script标签可以访问跨域资源的特性,通过在服务器端生成JSON格式的数据并拼接到一个JavaScript函数调用中,然后在客户端通过动态创建script标签来访问跨域接口并获取数据。
例如,在服务端返回JSONP格式数据:
@RequestMapping("/jsonp")
@ResponseBody
public String jsonp(String callback) {
String data = "{'name': 'Tom', 'age': 20}";
return callback + "(" + data + ")";
}
在客户端通过如下方式来获取数据:
<script>
function jsonpCallback(data) {
console.log(data);
}
var script = document.createElement('script');
script.src = 'http://example.com:8080/api/jsonp?callback=jsonpCallback';
document.head.appendChild(script);
</script>
以上是三种常用的解决Java跨域问题的方式,不同的应用场景可以选用不同的方案。