您的位置:首页 > 产品设计 > UI/UE

通过Filter解决跨域问题,可以跨多个域,域可以通过@Value注解取

2015-11-30 18:53 549 查看
跨域中不同的域指的是“协议+IP+端口”,只要其中一个不相同就要跨域访问,为了安全,浏览器对于跨域默认是禁止访问的。现在很多应用的客户端和服务端是分开的,那么如何来让处于不同域的客户端和服务端实现跨域访问呢,而且客户端还可能不止一个,那么又如何实现多客户端跨域访问一个服务端呢?


本文的项目默认使用Maven构建,并使用Spring Security实现安全,首先在src/main/resources目录建properties文件,在配置文件中输入Access-Control-Allow-Origin=http://192.168.1.1,http://192.168.1.2,http://192.168.1.3,代表客户端的三个域。(站点必须带"http://"还有端口号,这里使用默认端口号80,因此可以省略)

1、通过@Value注解从properties文件取字符串数组

建一个类,并使用@Component注解标注类,属性适用@Value注解,注意引用org.springframework.beans包。

@Component
public class MyFilter {

@Value("${Access-Control-Allow-Origin:}")// 这里的冒号加与不加感觉没区别
String[] originProperties; // 这里竟然可以直接以数组接收以逗号分隔的多个属性

}


这样就可以直接得到客户端来源域的数组。

有的时候@Value取不到值,问题大概有几个:

  1. resources下有很多xml文件

  2. 属性以com.开头

  3. 如果 resources下同时存在 application.yml,这个文件里也必须要有这个属性

  4. 属性不能是static

2、通过Filter设置响应头的"Access-Control-Allow-Origin"

"Access-Control-Allow-Origin"是响应头的信任站点,只可以设置一个站点。让刚建的类继承javax.servlet.Filter,重写doFilter方法,把所有请求的HttpServletResponse的Header的"Access-Control-Allow-Origin"设置信任站点。注意引用javax.servlet包。

httpServletResponse.setHeader("Access-Control-Allow-Origin", "http://192.168.1.72");


当然,通过这种方式只能实现跨一个域。

3、 跨多个域

"Origin"属性表示请求头的请求来源,通过第1步的方法已经从properties取多个域名的数组,通过下边这句代码来取得访问来源,判断该访问来源是否在域名数组中。

<pre name="code" class="java"><span style="white-space:pre">	</span>// 解决跨域问题,把几个客户端来源添加信任
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;

String curOrigin = httpRequest.getHeader("Origin");
System.out.println("当前访问来源是:"+curOrigin);
// 如果当前访问来源在application.properties的Access-Control-Allow-Origin配置范围内,则允许访问,否则不允许
if(curOrigin != null) {
for (int i = 0; i < originProperties.length; i++) {
//System.out.println("允许跨域访问的来源是:"+originProperties[i]);
if(curOrigin.equals(originProperties[i])) {
httpResponse.setHeader("Access-Control-Allow-Origin", curOrigin);
}
}
} else { // 对于无来源的请求(比如在浏览器地址栏直接输入请求的),那就只允许我们自己的机器可以吧
httpResponse.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1");
}
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT,HEAD");
// 请求来自哪个域,我就允许哪个域的来源,也就是说允许所有域访问服务,这也太不安全了
//if(httpRequest.getHeader("Origin") != null){
//	httpResponse.setHeader("Access-Control-Allow-Origin", curOrigin);
//}

// 这句千万别忘,让Filter按默认方式处理请求和响应,如果没写,那么response里没有body
chain.doFilter(request, response);
}


这样就会根据用户的来源来设置允许跨域的来源:"Access-Control-Allow-Origin"。

4. 跨域中的安全

如果你使用Spring Security,它是通过过滤器链来实现安全的,它的过滤器默认优先级最高,会第一个拦截请求。因此要把我们自己的跨域的Filter设置成优先级最高:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
MyFilter myFilter;

protected void configure(HttpSecurity http) throws Exception {
//Spring Security的filter默认再整个filter chain的最前边,因此需要把我们自己写的跨域的filter放在最前边
http.addFilterBefore(myFilter, ChannelProcessingFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
}
}


本文不是重点讲Spring Security,因此只是写了简单的例子。通过这种方式,而不使用JSONP,我们就可以实现跨多个域了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息