前言:在之前的文章中我已经对如何使用 CORS 处理跨域请求进行了介绍,在本文中,我将介绍如何在 CORS 跨域的情况下设置和获取 Cookie,以及在处理跨域 Cookie 中可能遇到的问题:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
CORS 跨域中的 Cookie
概述
配置说明
要想浏览器处理 CORS 跨域中的 Cookie 只需要分别在网页以及服务端作出一点点改变:
-
网页端中,对于跨域的
XMLHttpRequest
请求,需要设置withCredentials
属性为 true。var xhr = new XMLHttpRequest(); xhr.open("GET", xhr.withCredentials = true; // 设置跨域 Cookie xhr.send();
-
同时服务端的响应中必须携带
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
首部。
最后,跟上面一样,在 Java Web 应用程序中获取和设置 Cookie 方法与普通的没有区别。