Spring MVC 跨域问题 我不是女神ヾ 2022-06-14 06:39 143阅读 0赞 # 创建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标志支持的方法。 ![这里写图片描述][SouthEast] 第二次才是真正的请求。 这个方案是利用了w3c的最新规范,所以该方案依赖浏览器的实现。 总结: 出现Access control allow origin错误,说明是跨域请求失败!浏览器发送请求成功,同时浏览器也接收到响应了,但是限制了XmlHttpRquest接收请求,不会让xmlhttprequest接受到响应,并且在js控制台报错。 这也就是我们在网络控制台(Network)能看见http 状态码是200,但是在js控制台(Console)出现js错误的原因。 [SouthEast]: /images/20220614/c16ac575611a49acaaf52cb7588bd685.png
还没有评论,来说两句吧...