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

说明

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

本文适用 简单请求 携带 cookie非简单请求 携带 cookie

原因详见 链接

filter 过滤器

关键代码

Access-Control-Allow-Origin 头

允许可访问的域列表,携带cookie时,不能是 *,必须前端服务器域名,而且末尾不能有符号: /,如下:

response.setHeader("Access-Control-Allow-Origin", "http://localhost:9528");

Access-Control-Allow-Headers 头

携带cookie时,不能是 *,如下:

response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");

解释:

  • X-Requested-With:前端发请求可以携带 X-Requested-With,后端用来判断是否 ajax 请求。如果前端使用 axios,默认不携带该头,需要额外指定,详见 链接

Access-Control-Allow-Credentials 头

允许浏览器发送 cookie

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

完整代码

package com.zrgj.epidemic.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", "*");//允许可访问的域列表
        //允许可访问的域列表,携带cookie时,不能是 *,必须填域名,而且末尾不能有符号: /
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:9528");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");//设置 Preflight 请求缓存多长时间(以秒为单位)。
        //携带cookie时,不能是 *
        response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
//        response.setHeader("Access-Control-Allow-Headers", "*");
        //允许浏览器发送 cookie
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

注解配置

如果使用注解启用过滤器,加上下面注解:

@WebFilter("/*")

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
        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 发送post请求,默认是 application/json ,所以是 非简单请求

// 携带 cookie
axios.defaults.withCredentials = true;
// 携带 X-Requested-With
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.post('http://localhost:8080/login', 
 {
   "username":this.loginForm.username,
   "password":this.loginForm.password
 }
)
.then((res) => {
    console.log(res);
    this.loading = false
})
.catch(function (error) {// 请求失败处理
    console.log(error);
});

axios 简单请求

get 请求携带 cookie:

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

get 请求携带 cookie 的另一种方式:

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

原文出处:https://www.malaoshi.top/show_1IX46QGBvoNw.html