Java后端跨域Filter的较为优雅的实现方式
一般你可以自己实现Filter
@Component
public class CrossFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO 这里添加你要设置的响应头。
}
}
你需要记住的是:跨域保护,目的是保护用户在该服务端的权益,保护的是服务端。所以,跨域问题的解决绝大多数都是解决服务端设置的问题。
springboot自带的Filter,如下:
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class WebConfig {
private List<String> allowDomains =Arrays.asList("http://tools.bigbrotherlee.com","http://localhost:8080");
private List<String> allowHeaders =Arrays.asList("Authorization","Cookie","Token","content-type");
private List<String> exposedHeaders=Arrays.asList("Content-Disposition");
@Bean
public CorsFilter corsFilter() {
// 1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
// 1) 允许通过的域,不要写*,否则cookie就无法使用了
allowDomains.forEach(config::addAllowedOrigin);
// 2) 是否发送Cookie信息
config.setAllowCredentials(true);
// 3) 允许的请求方式
config.addAllowedMethod("*");
// 4)允许的头信息
allowHeaders.forEach(config::addAllowedHeader);
config.setExposedHeaders(exposedHeaders);
// 2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
// 3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
- 参数
只有五个参数,他们是向关联的
// setAllowedOrigins 设置允许跨域的域名,可以使用表示所有域名 可以使用.xxx.com表示所有子域名,在设置为AllowCredentials为true的时候不允许使用*
configuration.setAllowedOrigins(List.of("http://localhost:5173"));
// setAllowedMethods设置允许跨域的method,可以使用*表示全部
configuration.setAllowedMethods(List.of("*"));
// setAllowedHeaders设置允许携带的header,这里需要包含所有你需要的非正常允许的header,包括你自己自定义的
configuration.setAllowedHeaders(List.of("*"));
// 允许的自定义header
configuration.setExposedHeaders(List.of("*"));
// 是否允许携带认证信息(敏感信息),比如Cookie,在设置为true的时候不允许AllowedOrigins通配符,
// 同时前端需要配合设置withCredentials才会携带Cookie
configuration.setAllowCredentials(true);
// 携带Cookie
在跨域的服务端给前端设置Cookie时需要同时设置
- cookie.setAttribute("SameSite", "None"); // 表示不是同源Cookie
- cookie.setSecure(true); // 表示只在https环境下
此时在https环境下设置Cookie就会浏览器保存了,否则都不会保存。
可以看到,为了保护浏览器自带行为的Cookie,做了很多限制,所以在通常情况下我们不使用Cookie,而是自定义header比如token来做跨域
另外:
一些请求:比如有自定义头,非get,post,head请求或者带有Cookie这样的有用户隐私的头;需要在浏览器做正式请求服务器动作之前会先做一个options请求以确定服务端允不允许。总之,跨域是为了保护服务端和保护用户在服务端的数据(包括服务端存在本地与服务端存在远端的数据)。