过滤器filter实现跨域,简单请求携带cookie

说明

新版Chrome浏览器导致 cookie 跨域失败,详见:cookie跨域失败-新版chrome浏览器SameSite属性

适用场景

本文只适用 简单请求 携带 cookie,原因详见 链接

非简单请求 携带 cookie,详见 链接

filter代码

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 处理跨域的过滤器
 */
@WebFilter("/*")
public class CORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");//允许可访问的域列表
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");//设置 Preflight 请求缓存多长时间(以秒为单位)。
        //response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");//允许携带cookie。还需要ajax配合,见下面例子


        chain.doFilter(req, res);

    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}

}

解释

Access-Control-Allow-Origin 头

允许可访问的前端服务器列表,* 表示允许任意服务器

注意:末尾不能有符号: /,如下:

response.setHeader("Access-Control-Allow-Origin", "*");

Access-Control-Allow-Headers 头

告诉前端,发请求时,允许携带的请求头,*,表示允许所有请求头

如下:

response.setHeader("Access-Control-Allow-Headers", "*");

Access-Control-Allow-Methods 头

表示允许请求方法,如:POST, GET, OPTIONS, DELETE, HEAD, PUT

response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");

Access-Control-Allow-Credentials 头

true 表示允许携带 cookie,还需要ajax配合

response.setHeader("Access-Control-Allow-Credentials", "true");

设置 Preflight 请求缓存时间

非简单请求,先发送 OPTIONS 请求,该请求称为:Preflight 预检请求,然后才发送正式请求

该设置表示:在一段时间内,不再发送Preflight 预检请求,以秒为单位

response.setHeader("Access-Control-Max-Age", "3600");

提示:由于本文适用 简单请求,所以被设置不写也可以

注解配置

在类名上,加下面注解:

@WebFilter("/*")

类名

类名必须是 A0CORSFilter,即:以 A0开头

因为使用 @WebFilter 注解,无法指定过滤器的执行顺序,只会根据 类名 的 ascii码 的顺序,作为 执行顺序,所以为了保证 最先执行该跨域过滤器,类名以 A0开头

web.xml 配置

如果使用 web.xml 配置启用过滤器,加上下面配置:

<filter>
    <filter-name>CORSFilter</filter-name>
    <filter-class>top.malaoshi.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

ajax

jquery

$.ajax({
    url:baseUrl+'goods/list',
    type:'post',
    dataType:'json',//服务器端返回的数据格式是json
    xhrFields: { // 默认跨域时不携带cookie,需要指明携带cookie
        withCredentials: true
    },
    data: {
        "status":1
    },//发给服务器端的数据
    success:function(res){   //data:服务器端返回给浏览器端的数据
        if(res.code==0){
            console.log(res)
        }else{
            alert(res.msg);
        }
    },
    error:function (XMLHttpRequest, textStatus, errorThrown) {
        alert(XMLHttpRequest);
        alert(textStatus);
        alert(errorThrown);
    }

});

axios

axios.get(
    baseUrl+'goods/list?status=1',
    {withCredentials: true}//带cookie
).then(function(res){
    console.log(res.data);
})

或者

axios.defaults.withCredentials = true;//带cookie
axios.get(baseUrl+'goods/list?status=1').then(function(res){
    console.log(res.data);
})

原文出处:/show_1IXDkwyybXc.html