概念
在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址,
而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。
这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域即我们常说的浏览器请求的同源策略。
Jsonp
在前后端分离的项目中,会经常遇到需要跨域请求的问题。跨域请求有多种方式。之前接触过jsonp的方式。
这种方式是在前端页面进行跨域请求兼容性好,但安全性比较差,只支持GET请求。
CORS
Cross-Origin Resource Sharing 即跨源资源共享 。是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。
也就是说它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpReuest 请求,从而克服 Ajax 只能同源使用的限制。
Http头部字段介绍
Access-Control-Allow-Origin:响应首部中可以携带这个头部表示服务器允许哪些域可以访问该资源
Access-Control-Allow-Methods:该首部字段用于预检请求的响应,指明实际请求所允许使用的HTTP方法
Access-Control-Allow-Headers:该首部字段用于预检请求的响应。指明了实际请求中允许携带的首部字段
Access-Control-Max-Age:该首部字段用于预检请求的响应,指定了预检请求能够被缓存多久
Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器
具体实现
这里通过过滤器的方式对请求进行拦截。设置http的响应header来实现。
public class CrossFilter implements Filter {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request=(HttpServletRequest)servletRequest;
HttpServletResponse response=(HttpServletResponse)servletResponse;
logger.info("【允许跨域访问】refererUrl【{}】", request.getHeader("Referer"));
//允许跨域访问
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "https://monline.01zhuanche.com");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
response.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,userId,Authorization,SessionToken,JSESSIONID,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed","1");
filterChain.doFilter(request, response);
}
public static String getRefererUrl(HttpServletRequest request){
String returnValue = null;
if(request != null && !StringUtils.isEmpty(request.getHeader("Referer"))) {
returnValue = request.getHeader("Referer");
String[] urls = returnValue.split("/");
if(urls != null && urls.length > 3) {
returnValue = urls[0] + "//" + urls[2];
}
}
return returnValue;
}
@Override
public void destroy() {
}
}
此外需要对我们的过滤器进行配置,在web.xml文件中添加如下配置:
<filter>
<filter-name>crossDomainFilter</filter-name>
<filter-class>com.open.advertise.api.cooperation.filter.CrossFilter</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>crossDomainFilter</filter-name>
<url-pattern>/*</url-pattern> <!--可以针对某个接口进行限制-->
</filter-mapping>
以上,对于设置的跨域请求的域名就可以进行跨域访问啦。