1、第一种:
public class CorsFilter extends OncePerRequestFilter {
static final String ORIGIN = "Origin";
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String origin = request.getHeader(ORIGIN);
response.setHeader("Access-Control-Allow-Origin", "*");//* or origin as u prefer
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "PUT, POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "content-type, authorization");
if (request.getMethod().equals("OPTIONS"))
response.setStatus(HttpServletResponse.SC_OK);
else
filterChain.doFilter(request, response);
}
}
@Bean
public CorsFilter corsFilter() throws Exception {
return new CorsFilter();
}
http
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
.headers()
.cacheControl();
在服务端添加addHeader,请看下面,服务端添加header。
解决 spring boot 自定义过滤器跨域问题
使用自定义过滤器的时候
使用自定义过滤器时,采用注解@CrossOrigin会失效,所以用以下代码来搞定
public class TokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServlet Requestrequest, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// do something
cors(request, response);
// do something
}
private void cors(HttpServletRequest request, HttpServletResponse response) {
String allowOrigin = request.getHeader("Origin");
String allowMethods = "GET,PUT, POST, DELETE";
String allowHeaders = "Origin,No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified,Cache-Control, Expires, Content-Type, X-E4M-With";
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Headers", allowHeaders);
response.addHeader("Access-Control-Allow-Methods", allowMethods);
response.addHeader("Access-Control-Allow-Origin", allowOrigin);
}
}
2、第二种:
@Configuration
public class CorsConfig {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置你要允许的网站域名,如果全允许则设为 *
config.addAllowedOrigin("http://localhost:4200");
// 如果要限制 HEADER 或 METHOD 请自行更改
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
// 这个顺序很重要哦,为避免麻烦请设置在最前
bean.setOrder(0);
return bean;
}
}
跨域其他问题
在跨域的时,客户端能够访问到一些默认响应的headers:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
那么默认情况下,客户端只能访问到以上headers,如果是其他则不行
因为我们要访问的是headers中的Authorization,axios的配置代码如下(部分),
axios.interceptors.response.use((res) => {
// do something
// 默认情况下 res.headers.authorization 的值是undefined,headers中没有authorization
if (res.headers.authorization) {
sessionStorage.setItem('authorization', res.headers.authorization);
}
// do something
}
解决问题办法,可以自定义添加
response.addHeader(“Access-Control-Expose-Headers”, “Authorization”);
这个Access-Control-Expose-Headers的作用是:
Access-Control-Expose-Headers相当于一个服务器的headers白名单,可以让客户端进行访问例如:
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
这样设置完后 X-My-Custom-Header and X-Another-Custom-Header 就能被客户端所访问。
解决完获取res.headers.authorization 的值为undefined的问题,又有个新的问题。就是Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
新问题解决:
在服务端的Access-Control-Allow-Headers中添加 Authorization,完美解决,例如:
String allowHeaders = "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authorization";
response.addHeader("Access-Control-Allow-Headers", allowHeaders);