CORS 跨域中的 Cookie處理

原文鏈接:https://www.jianshu.com/p/13d53acc124f

CORS 跨域中的 Cookie

概述

​ 基於安全方面的考慮,在瀏覽器中無法獲取跨域的 Cookie 這一點時永遠不變的。但是我們處理跨域請求時有可能會遇到這樣的情況:一個網頁與域爲bbb.cn的服務器正常發送請求和接收響應,同時這個網頁也需要跨域訪問aaa.cn服務器。

​ 衆所周知,瀏覽器會在準備發送的請求中附上所有符合要求的Cookie,故在上面的情況中瀏覽器會自動處理網頁與域爲bbb.cn的服務器之間的 Cookie;但是在 CORS 跨域中,瀏覽器並不會自動發送 Cookie,也就是說,瀏覽器不會處理網頁與aaa.cn服務器之間的 Cookie。

配置說明

要想瀏覽器處理 CORS 跨域中的 Cookie 只需要分別在網頁以及服務端作出一點點改變:

  1. 網頁端中,對於跨域的 XMLHttpRequest 請求,需要設置withCredentials 屬性爲 true。

    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://aaa.cn/localserver/api/corsTest");
    xhr.withCredentials = true; // 設置跨域 Cookie
    xhr.send();
    
  2. 同時服務端的響應中必須攜帶 Access-Control-Allow-Credentials: true 首部。如果服務端的響應中未攜帶Access-Control-Allow-Credentials: true 首部,瀏覽器將不會把響應的內容返回給發送者。

要想設置和獲取跨域 Cookie,上面提到的兩點缺一不可。另外有一點需要注意的是:規範中提到,如果 XMLHttpRequest 請求設置了withCredentials 屬性,那麼服務器不得設置 Access-Control-Allow-Origin的值爲* ,否則瀏覽器將會拋出The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 錯誤。

在基於 Filter 的 CORS 跨域中應用 Cookie

​ 基於 Filter 的 CORS 跨域實現實際上就是手動在響應中添加 CORS 要求的響應首部字段。一個簡單 Filter 實現如下:

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("work");
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    filterChain.doFilter(servletRequest, servletResponse);
}

但是正如上面提到的:如果 XMLHttpRequest 請求設置了withCredentials 屬性,那麼服務器不得設置 Access-Control-Allow-Origin的值爲* ,所以我們需要處理Access-Control-Allow-Origin 首部字段的值,否則將會得到以下的錯誤:

下面提供一種處理Access-Control-Allow-Origin 首部字段值的方法,我們可以根據請求的域來動態的設置:

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    String origin = request.getHeader("origin");// 獲取源站
    response.setHeader("Access-Control-Allow-Origin", origin);
    response.setHeader("Access-Control-Allow-Methods", "POST, GET");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    filterChain.doFilter(servletRequest, servletResponse);
}

最後,在 Java Web 應用程序中獲取和設置 Cookie 方法與普通的沒有區別。

Cookie cookie = new Cookie("test", "value");
response.addCookie(cookie);

Cookie[] cookies = request.getCookies();

在基於@CorssOrigin 註解的 CORS 跨域中應用 Cookie

​ 在使用 Spring 提供的 CORS 支持的 @CorssOrigin 註解時,我們只需要在網頁端設置跨域 XMLHttpRequest 請求的 withCredentials 屬性就可以正常設置和獲取跨域 Cookie。這是因爲 Spring 的@CorssOrigin 註解默認情況下已經爲我們設置響應中的 Access-Control-Allow-Credentials: true 首部,同時也會根據實際接收到的請求的源站設置 Access-Control-Allow-Origin首部。

​ 在 Spring MVC 中配置使用 CORS跨域的方法我已經在前面的文章中介紹過,詳細的可以閱讀文章Spring MVC 實現 CORS 跨域。 使用@CorssOrigin 註解後服務器設置 Cookie 的響應首部如下圖所示:

​ 最後,跟上面一樣,在 Java Web 應用程序中獲取和設置 Cookie 方法與普通的沒有區別。



作者:ken_ljq
鏈接:https://www.jianshu.com/p/13d53acc124f
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章