前言:在之前的文章中我已經(jīng)對(duì)如何使用 CORS 處理跨域請(qǐng)求進(jìn)行了介紹雇锡,在本文中,我將介紹如何在 CORS 跨域的情況下設(shè)置和獲取 Cookie蔓榄,以及在處理跨域 Cookie 中可能遇到的問題:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
CORS 跨域中的 Cookie
概述
? 基于安全方面的考慮忽匈,在瀏覽器中無法獲取跨域的 Cookie 這一點(diǎn)時(shí)永遠(yuǎn)不變的。但是我們處理跨域請(qǐng)求時(shí)有可能會(huì)遇到這樣的情況:一個(gè)網(wǎng)頁(yè)與域?yàn)?code>bbb.cn的服務(wù)器正常發(fā)送請(qǐng)求和接收響應(yīng)墓赴,同時(shí)這個(gè)網(wǎng)頁(yè)也需要跨域訪問aaa.cn
服務(wù)器。
? 眾所周知航瞭,瀏覽器會(huì)在準(zhǔn)備發(fā)送的請(qǐng)求中附上所有符合要求的Cookie诫硕,故在上面的情況中瀏覽器會(huì)自動(dòng)處理網(wǎng)頁(yè)與域?yàn)?code>bbb.cn的服務(wù)器之間的 Cookie;但是在 CORS 跨域中刊侯,瀏覽器并不會(huì)自動(dòng)發(fā)送 Cookie章办,也就是說,瀏覽器不會(huì)處理網(wǎng)頁(yè)與aaa.cn
服務(wù)器之間的 Cookie滨彻。
配置說明
要想瀏覽器處理 CORS 跨域中的 Cookie 只需要分別在網(wǎng)頁(yè)以及服務(wù)端作出一點(diǎn)點(diǎn)改變:
-
網(wǎng)頁(yè)端中藕届,對(duì)于跨域的
XMLHttpRequest
請(qǐng)求,需要設(shè)置withCredentials
屬性為 true亭饵。var xhr = new XMLHttpRequest(); xhr.open("GET", "http://aaa.cn/localserver/api/corsTest"); xhr.withCredentials = true; // 設(shè)置跨域 Cookie xhr.send();
同時(shí)服務(wù)端的響應(yīng)中必須攜帶
Access-Control-Allow-Credentials: true
首部休偶。如果服務(wù)端的響應(yīng)中未攜帶Access-Control-Allow-Credentials: true
首部,瀏覽器將不會(huì)把響應(yīng)的內(nèi)容返回給發(fā)送者辜羊。
要想設(shè)置和獲取跨域 Cookie椅贱,上面提到的兩點(diǎn)缺一不可懂算。另外有一點(diǎn)需要注意的是:規(guī)范中提到,如果 XMLHttpRequest
請(qǐng)求設(shè)置了withCredentials
屬性庇麦,那么服務(wù)器不得設(shè)置 Access-Control-Allow-Origin
的值為*
计技,否則瀏覽器將會(huì)拋出The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
錯(cuò)誤。
在基于 Filter 的 CORS 跨域中應(yīng)用 Cookie
? 基于 Filter 的 CORS 跨域?qū)崿F(xiàn)實(shí)際上就是手動(dòng)在響應(yīng)中添加 CORS 要求的響應(yīng)首部字段山橄。一個(gè)簡(jiǎn)單 Filter 實(shí)現(xiàn)如下:
@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
請(qǐng)求設(shè)置了withCredentials
屬性垮媒,那么服務(wù)器不得設(shè)置 Access-Control-Allow-Origin
的值為*
,所以我們需要處理Access-Control-Allow-Origin
首部字段的值航棱,否則將會(huì)得到以下的錯(cuò)誤:
下面提供一種處理Access-Control-Allow-Origin
首部字段值的方法睡雇,我們可以根據(jù)請(qǐng)求的域來動(dòng)態(tài)的設(shè)置:
@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 應(yīng)用程序中獲取和設(shè)置 Cookie 方法與普通的沒有區(qū)別饮醇。
Cookie cookie = new Cookie("test", "value");
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
在基于@CorssOrigin 注解的 CORS 跨域中應(yīng)用 Cookie
? 在使用 Spring 提供的 CORS 支持的 @CorssOrigin
注解時(shí)它抱,我們只需要在網(wǎng)頁(yè)端設(shè)置跨域 XMLHttpRequest
請(qǐng)求的 withCredentials
屬性就可以正常設(shè)置和獲取跨域 Cookie。這是因?yàn)?Spring 的@CorssOrigin
注解默認(rèn)情況下已經(jīng)為我們?cè)O(shè)置響應(yīng)中的 Access-Control-Allow-Credentials: true
首部朴艰,同時(shí)也會(huì)根據(jù)實(shí)際接收到的請(qǐng)求的源站設(shè)置 Access-Control-Allow-Origin
首部观蓄。
? 在 Spring MVC 中配置使用 CORS跨域的方法我已經(jīng)在前面的文章中介紹過,詳細(xì)的可以閱讀文章Spring MVC 實(shí)現(xiàn) CORS 跨域祠墅。 使用@CorssOrigin
注解后服務(wù)器設(shè)置 Cookie 的響應(yīng)首部如下圖所示:
? 最后侮穿,跟上面一樣,在 Java Web 應(yīng)用程序中獲取和設(shè)置 Cookie 方法與普通的沒有區(qū)別毁嗦。