Spring MVC 跨域问题

创建Interceptor

package com.jeiker.commons.csrf;

import ...

/**
 * @Author : xiao
 * @Date : 17/6/12 下午3:22
 */
public class CORSInterceptor implements HandlerInterceptor{

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {

        response.addHeader("Access-Control-Allow-Origin", "*");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

    }
}

配置拦截器

spring-mvc.xml 的配置文件中配置拦截器:

<!-- 配置cors拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/operation/**"/>
        <bean class="com.jeiker.commons.csrf.CORSInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

说明:

使用通配符*,允许所有跨域访问,所以跨域访问成功。

但是,请注意使用通配符*,会允许来自任意域的跨域请求访问成功,这是比较危险的,所以在生产环境通常会做更精确控制。

简单请求

上述请求是简单请求,只要添加了Access-Control-Allow-Origin:*,就会访问成功,如果是复杂请求,我们需要更进一步的处理,才能成功。

这里先解释一下什么是简单请求和复杂请求。

Simple requests  

A simple cross-site request is one that meets all the following conditions:  

The only allowed methods are:  
GET  
HEAD  
POST  

Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:  

Accept  
Accept-Language  
Content-Language  
Content-Type  
The only allowed values for the Content-Type header are:  
application/x-www-form-urlencoded  
multipart/form-data  
text/plain  

复杂请求

在正式post之前,浏览器会先发出一个options请求(也叫preflight),同时header带上origin还有Access-Control-Request-*:*之类的头,服务器响应会返回相应的access-control-allow-origin,如果匹配,那么浏览器就会发送正式post,否则就会出现上述错误。这也解答了,跨域访问时,我们明明发送的post请求,失败的话,查看chrome network会发现是options方法的原因。

根据上述过程,后台方法额外需要options方法。

@RequestMapping(value = "/login",method=RequestMethod.OPTIONS)  
public void aActionOption(HttpServletResponse response ) throws IOException{  

    System.out.println("option execute.....");  
    response.setHeader("Access-Control-Allow-Headers", "accept, content-type");  
    response.setHeader("Access-Control-Allow-Method", "POST");  
    response.setHeader("Access-Control-Allow-Origin", "http://192.168.192.32");  
}  
@RequestMapping(value = "/login",method=RequestMethod.POST)  
    public void aAction(HttpServletResponse response ) throws IOException{  

        System.out.println("login execute.....");  
    }  

第一次是options请求,http options请求跟get、post、head等一样,都属于http的请求方法,options方法,用来获取服务器端某url支持的方法,response header中allow标志支持的方法。

这里写图片描述

第二次才是真正的请求。

这个方案是利用了w3c的最新规范,所以该方案依赖浏览器的实现。

总结:

出现Access control allow origin错误,说明是跨域请求失败!浏览器发送请求成功,同时浏览器也接收到响应了,但是限制了XmlHttpRquest接收请求,不会让xmlhttprequest接受到响应,并且在js控制台报错。

这也就是我们在网络控制台(Network)能看见http 状态码是200,但是在js控制台(Console)出现js错误的原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值