CORS是解决浏览器跨域限制的W3C标准,详见:https://www.w3.org/TR/cors/。
根据CORS标准的定义,在浏览器中访问跨域资源时,须要作以下实现:java
Access-Control-Allow-Origin
,值为服务端容许访问资源的域名称,同时浏览器会根据该值与发起的请求消息头Origin
值进行匹配,以确认服务端是否容许访问跨域资源。Origin
值以决定是否容许浏览器访问跨域资源,返回相应的消息头。具体来讲,在实现时一般须要设置以下几个响应消息头:ajax
Access-Control-Allow-Origin
:“origin-list” | “null” | “*”,容许访问跨域资源的域名列表,对于预检请求来讲,决定是否会发送实际请求。Access-Control-Allow-Credentials
:true | false,代表实际请求中是否能够包含用户凭证信息。Access-Control-Allow-Methods
:“method”,服务端容许访问的实际请求方法名列表。Access-Control-Allow-Headers
:“field-name”,在“实际”请求中能够包含的消息头名称列表。Access-Control-Max-Age
:seconds,预检请求结果缓存时间,单位:秒。在该时间范围内,发送实际请求以前再也不会发送预检请求。特别说明:对于须要跨域传递Cookie的场景,必须设置消息头“Access-Control-Allow-Credentials”为“true”,且此时“Access-Control-Allow-Origin”值只能为某一指定单一域名。
简而言之,CORS标准的核心就是:服务端须要在浏览器的跨域请求响应中包含指定消息头,以下经过代码示例说明。spring
public class AjaxCorsServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(AjaxCorsServlet.class.getName()); @Override protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String origin = req.getHeader("Origin"); String allowMethod = req.getHeader("Access-Control-Request-Method"); String allowHeaders = req.getHeader("Access-Control-Request-Headers"); resp.setHeader("Access-Control-Allow-Origin", origin);// 容许指定域访问跨域资源 resp.setHeader("Access-Control-Allow-Credentials", "true"); // 容许跨域传递Cookie resp.setHeader("Access-Control-Max-Age", "86400"); // 浏览器缓存预检请求结果时间,单位:秒 resp.setHeader("Access-Control-Allow-Methods", allowMethod);// 容许浏览器发送的实际请求方法名列表 resp.setHeader("Access-Control-Allow-Headers", allowHeaders);// 容许浏览器发送的请求消息头 } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { logger.info(String.format("ajax cors post do")); String origin = req.getHeader("Origin"); resp.setHeader("Access-Control-Allow-Origin", origin); // 在实际请求中容许指定域访问跨域资源 resp.setHeader("Access-Control-Allow-Credentials", "true"); // 容许跨域传递Cookie resp.setHeader("Content-Type", "application/json"); // 服务端响应的数据类型 User user = new User(); user.setName("ajax cors post do"); user.setPwd("******"); resp.getWriter().write(JSON.toJSONString(user)); } }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse resp = (HttpServletResponse)response; String origin = req.getHeader("Origin"); resp.setHeader("Access-Control-Allow-Origin", origin); // 容许指定域访问跨域资源 resp.setHeader("Access-Control-Allow-Credentials", "true"); // 容许跨域传递Cookie if(RequestMethod.OPTIONS.toString().equals(req.getMethod())) { String allowMethod = req.getHeader("Access-Control-Request-Method"); String allowHeaders = req.getHeader("Access-Control-Request-Headers"); resp.setHeader("Access-Control-Max-Age", "86400"); // 浏览器缓存预检请求结果时间,单位:秒 resp.setHeader("Access-Control-Allow-Methods", allowMethod); // 容许浏览器发送的实际请求方法名列表 resp.setHeader("Access-Control-Allow-Headers", allowHeaders); // 容许浏览器发送的请求消息头 return; } chain.doFilter(request, response); } @Override public void destroy() { // release resouces }
}json
Filter配置: ```xml <filter> <filter-name>CROSFilter</filter-name> <filter-class>org.chench.springdemo.filter.CROSFilter</filter-class> </filter> <filter-mapping> <filter-name>CROSFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
从Spring 4.2.0.RC1版本开始,Spring MVC提供了一个解决浏览器跨域限制的注解CrossOrigin
,只须要在Controller方法上使用该注解便可。跨域
@RequestMapping(value="/post", method = {RequestMethod.POST}) @ResponseBody @CrossOrigin(origin="*") // 使用CrossOrigin注解处理浏览器跨域限制问题 public User testAjaxCORSPost(HttpServletRequest req, HttpServletResponse resp, @RequestBody User user) { logger.info("ajax post do"); User u = new User(); u.setName("ajaxPost"); u.setPwd("111"); return u; }【参考】 https://spring.io/blog/2015/06/08/cors-support-in-spring-framework