引言
运行在 电动志趣享 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 http://domain-b.com/data 的请求。
出于安全性,浏览器限制脚本内发起的跨源 HTTP 请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。
概述
跨源资源共享 (CORS:Cross-Origin Resource Sharing,跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(源,对应主机,协议和端口),这样浏览器就可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。
解决方案一:跨域过滤器
自定义过滤器
// 跨域过滤器
public class CrosFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// 设置响应头
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Authorization, x-requested-with");
String curOrigin = request.getHeader("Origin");
System.out.println("跨域过滤器被执行,当前访问来源者为:" + curOrigin);
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
web.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--跨域访问过滤器-->
<filter>
<filter-name>crosFilter</filter-name>
<filter-class>com.fc.filter.CrosFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>crosFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
解决方案二:跨域拦截器
自定义拦截器
// 跨域拦截器
public class CrosInterceptor implements HandlerInterceptor {
// 访问前进行拦截
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
// 设置响应头
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, Authorization, Accept, X-Requested-With");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
System.out.println("跨域拦截器执行");
return true;
}
}
springMvc.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven/>
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.fc.controller"/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--指定拦截的路径-->
<mvc:mapping path="/crossOrigin/*"/>
<!--指定不拦截-->
<!--<mvc:exclude-mapping path=""/>-->
<!--自定义拦截器-->
<bean class="com.fc.interceptor.CrosInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>