通过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,我们就可以实现跨多个域了。
相关文章推荐
- vbs 解析json jsonp的方法
- 探秘ajax跨域请求
- MySQL之Field‘***’doesn’t have a default value错误解决办法
- ie7下利用ajax跨域盗取cookie的解决办法
- JavaScript中模拟实现jsonp
- javascript跨域的方法汇总
- 在Ajax中使用Flash实现跨域数据读取的实现方法
- 把input初始值不写value的具体实现方法
- 如何设置iframe高度自适应在跨域情况下的可用方法
- 使用script的src实现跨域和类似ajax效果
- js跨域问题之跨域iframe自适应大小实现代码
- JavaScript两种跨域技术全面介绍
- jquery 根据name名获取元素的value值
- ajax跨域(基础域名相同)表单提交的方法
- JS不能跨域借助jquery获取IP地址的方法
- jQuery获取Select选择的Text和Value(详细汇总)
- 一看就懂:jsonp详解
- jQuery跨域问题解决方案
- 详解JavaScript中jQuery和Ajax以及JSONP的联合使用
- jQuery操作Select选择的Text和Value(获取/设置/添加/删除)