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