Spring MVC经过CROS协议解决跨域问题

如今接手学校网络中心的一个项目,根据团队成员的实际状况以及开发须要,老师但愿作到先后端彻底分离。后台使用java提供restful API 做为核心,前台不管PC或者移动端能够共用一个核心。前期解决了哦oauth2,做为受权机制等问题,本觉得大业将成。(最近打算详细介绍一下机遇Spring sercurity 实现oauth2的解决方案)结果又出现了一个跨域问题,让咱们踩了一个大坑,记录在此,以绝后患。 错误信息以下: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403. 什么是跨域 简单的说即为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求。好比说,前端域名是www.abc.com,那么在当前环境中运行的js代码,出于安全考虑,访问www.xyz.com域名下的资源,是受到限制的。现代浏览器默认都会基于安全缘由而阻止跨域的ajax请求,这是现代浏览器中必备的功能,可是每每给开发带来不便。特别是对我这样后台开发人员来说,这个事情简直神奇。 但跨域的需求却一直都在,为了跨域,勤劳勇敢的程序猿们想出了许许多多的方法,例如,jsonP、代理文件等等。但这些作法增长了许多没必要要的维护成本,并且应用场景也有许多限制,例如jsonP并不是XHR,因此jsonP只能使用GET传递参数。更详细的资料能够看这里 Web应用跨域访问解决方案汇总 CORS协议 现在的JS大有一统天下的趋势,浏览器已经成了大多应用最好的安身之所。哪怕在移动端也有各类Hybird方案,在本地文件系统的Web页面,也有须要获取外部数据的需求,而这些需求也必然是跨域的。在寻找跨域解决方案时,发现了最优雅解决方案就是HTML5来带了的“Cross-Origin Resource Sharing”的新特性,来赋予开发者权力决定资源是否容许被跨域访问。 CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它容许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 为何说它优雅呢? 整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。 所以,实现CORS通讯的关键是服务器。只要服务器实现了CORS接口,就能够跨源通讯。 解决这个问题的关键就落在了我这个负责后台的程序猿身上。 看看文档也不是什么难事嘛,就是须要在http头中设置Access-Control-Allow-Origin来决定须要容许哪些站点来访问。关于CROS协议更详细内容参考跨域资源共享 CORS 详解 CROS常见header CORS具备如下常见的header Access-Control-Allow-Origin: http://kbiao.me Access-Control-Max-Age: 3628800 Access-Control-Allow-Methods: GET,PUT, DELETE Access-Control-Allow-Headers: content-type "Access-Control-Allow-Origin"代表它容许" http://kbiao.me "发起跨域请求 "Access-Control-Max-Age"代表在3628800秒内,不须要再发送预检验请求,能够缓存该结果(上面的资料上咱们知道CROS协议中,一个AJAX请求被分红了第一步的OPTION预检测请求和正式请求) "Access-Control-Allow-Methods"代表它容许GET、PUT、DELETE的外域请求 "Access-Control-Allow-Headers"代表它容许跨域请求包含content-type头 固然在处理这个问题的时候前端也有很多坑,特别是Chrome浏览器不容许localhost的跨域请求,详细方案见我项目中负责前端解决方案的小伙伴。伪装有连接 常规解决方案 知道了问题的缘由,也知道了配套的解决办法,如今就让咱们来实现解决。思路很简单,当前端要请求跨域资源时候,咱们给它加上响应的响应头便可。很显然咱们本身定义一个过滤器是最简单不过了。 /** * Created by kangb on 2016/5/10. */ @Component public class myCORSFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort(); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization"); response.setHeader("Access-Control-Allow-Credentials","true"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } @Component 是Spring的注解,关键部分在doFilter中,添加了咱们须要的头,option是预检测须要因此须要容许,Authorization是作了oauth2登陆响应所必须的,Access-Control-Allow-Credentials表示容许cookies。都是根据本身项目的实际须要配置。 再配置Web.xml使得过滤器生效 cors ·CLASS_PATH·.myeCORSFilter cors /api/* 接下来前端就能够像往常同样使用AJAX请求得到资源了,彻底不须要作出什么改变。 SPRING 4中更优雅的办法 SpringMVC4提供了很是方便的实现跨域的方法。在requestMapping中使用注解。 @CrossOrigin(origins = “http://kbiao.me”) 全局实现 .定义类继承WebMvcConfigurerAdapter,设置跨域相关的配置 public class CorsConfigurerAdapter extends WebMvcConfigurerAdapter{ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/*").allowedOrigins("*"); } } 将该类注入到容器中: 更详细的内容参考Spring 官方的hello world案例Enabling Cross Origin Requests for a RESTful Web Service http://spring.io/guides/gs/rest-service-cors/或者使用git下载示例源码 https://github.com/spring-guides/gs-rest-service-cors.git
 前端

相关文章
相关标签/搜索