1.web.xml允许跨域名单与允许接口跨域配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
......
<!--跨域处理开始 -->
<filter>
<filter-name>cros</filter-name>
<filter-class>com.kuayu.filter.AccessFilter</filter-class>
<init-param>
<param-name>allowDomainRequestUrl</param-name>
<param-value>
/IPermissionService/getVersionSecret.htm,
/IPermissionService/getVersionSecret
</param-value>
</init-param>
<init-param>
<param-name>allowDomain</param-name>
<param-value>
http://ces.bbc.com,
http://ces.bbc.com:80,
https://ces.bbc.com,
https://ces.bbc.com:80
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>cros</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--跨域处理结束 -->
......
</web-app>
2.跨域过滤器 AccessFilter 类
package com.kuayu.filter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@Component
public class AccessFilter extends HttpServlet implements Filter {
private static final long serialVersionUID = 1L;
/** 获取允许跨域请求的URL */
private Set<String> allowDomainRequestUrls = Collections.emptySet();
/** 获取允许跨域地址 */
private Set<String> allowDomains = Collections.emptySet();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String allowDomainRequestUrl = filterConfig.getInitParameter("allowDomainRequestUrl");
String allowDomain = filterConfig.getInitParameter("allowDomain");
//获取允许跨域请求的URL
allowDomainRequestUrls = strSplitConvertList(allowDomainRequestUrl,",");
//获取允许跨域地址
allowDomains = strSplitConvertList(allowDomain,",");
}
/**
* String分隔
* @param sourceStr
* @param split
* @return
*/
private Set<String> strSplitConvertList(String sourceStr,String split){
if(StringUtils.isBlank(sourceStr)){
return Collections.emptySet();
}
String[] sourceArray = StringUtils.split(sourceStr,split);
if(null == sourceArray || sourceArray.length == 0){
return Collections.emptySet();
}
Set<String> sets = new HashSet<String>();
for(String str : sourceArray){
if(StringUtils.isNotBlank(str)){
sets.add(str.trim());
}
}
return sets;
}
/**
* 是否包含请求Url
* @param includeURLs
* @param requestUrl
* @return
*/
public static boolean isIncludeUrl(Set<String> includeURLs, String requestUrl){
if(CollectionUtils.isEmpty(includeURLs)){
return Boolean.FALSE;
}
for(String includeURL : includeURLs){
if(requestUrl.endsWith(includeURL)){
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String requestUrl = httpRequest.getServletPath();
//获取请求的域名
String originHeader= httpRequest.getHeader("Origin");
//如果请求的域为允许跨域的域名 且 请求URL为允许跨域的URL
if (allowDomains.contains(originHeader) && isIncludeUrl(allowDomainRequestUrls,requestUrl)){
httpResponse.setHeader("Access-Control-Allow-Origin", originHeader);
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
//表明服务器支持的所有头信息字段
httpResponse.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,token,X-Test-TOKEN");
//如果要把Cookie发到服务器,需要指定Access-Control-Allow-Credentials字段为true;
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpResponse.setHeader("XDomainRequestAllowed","1");
/* Cookie[] cookies = httpRequest.getCookies();
// 然后迭代之
String token = "USER_ID";
if (cookies != null && cookies.length > 0) { //如果没有设置过Cookie会返回null
for (Cookie cookie : cookies) {
if(cookie.getName().equals("token")){
token = cookie.getValue();
}
}
}
Cookie cookie = new Cookie("token",token);
cookie.setPath("/");
httpResponse.addCookie(cookie);*/
}
chain.doFilter(request, httpResponse);
}
}
3.常见问题
a.针对特定接口跨域时,跨域逻辑需要放入过滤类中来实现,请求方式Object在到接口之前已被拦截了。
b.请求未跨域时, String originHeader= httpRequest.getHeader("Origin");获取内容为空对象。