1. 跨域问题简介
还是要简单介绍一下跨域的原因——同源策略。
同源策略是浏览器上为安全性考虑实施的的安全策略。
两个页面地址中的协议、域名和端口号一致,则表示同源。
同源策略的限制:
- 存储在浏览器中的数据,如localStroage、Cookie和IndexedDB不能通过脚本跨域访问
- 不能通过脚本操作不同域下的DOM
- 不能通过ajax请求不同域的数据
所以,只要是请求不同 协议、域名和端口号 就会产生跨域的问题,这在前后端开发中是很常见的问题,我也是在写毕设中遇到了这个问题。
2. 解决原理
浏览器有同源策略,但是并不代表浏览器就不允许跨域的产生。
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。
这是官方的解释,其实就是服务器告诉浏览器,哪些URl可以进行跨域访问
2. 三种解决方案
2.1 方案一: Filter
- 编写一个Filter
package com.ken.localserver.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CORSFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("work");
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
- 然后在 web.xml 文件中配置该过滤器
<!-- CORS Filter -->
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>com.ken.localserver.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.2 方案二: @CrossOrigin
使用SpringMVC的@CrossOrigin注解来实现CORS 跨域
作用位置:
@CrossOrigin可以作用在类、方法上
- 当作用在方法上时,是表示该方法拦截的URL能够跨域访问
- 当作用在类上时,该类下所有URL都能够跨域访问
参数:
如果不写参数,就表示允许来自任意的源站以及任意 HTTP 请求方法的请求访问(这样不是非常好)
@CrossOrigin(origins = “http://127.0.0.1:3000”, maxAge = 3600)
- origins :表示来源,也就是前端请求的地址。
- allowedHeaders :允许request携带的请求头。
- exposedHeaders :用户代理将允许客户端访问的响应头列表。(不是很清楚,知道的大佬可以评论一下)
- methods:请求的方式,例如:GET,POST,PUT,DELETE等。
- maxAge:缓存存储的最大时间。
2.3 方案三(推荐): <mvc:cors>
SpringMVC已经支持CORS(Spring MVC 版本必须是 4.2 及以上),我们只需要在SpringMVC的配置文件中进行一些配置即可。
像SpringMVC的配置文件中添加以下代码
<mvc:cors>
<mvc:mapping path="/**"
allowed-origins="http://localhost:3000,http://127.0.0.1:3000,http://localhost:9528,http://127.0.0.1:9528"
allowed-methods="GET,POST,PUT,POST,DELETE"
max-age="3600" />
</mvc:cors>
参数介绍:
- path:能够跨域的路径,这个其实就相当于方法一中Filter拦截的路径。
- allowed-origins:表示来源,也就是前端请求的地址。
- allowed-methods:请求的方式,例如:GET,POST,PUT,DELETE等。
- max-age:缓存存储的最大时间。
完成配置后重启服务器,前端代码不需要改变