实际前端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跨域问题的方式,不同的应用场景可以选用不同的方案。