springboot web的4种允许跨域的方式
跨域产生的条件
-
浏览器异步请求
- 协议不同,如一个为
http
,一个为https
- IP或域名不同
- 端口不同 比如你在
a.com:80
的域名页面访问a.com:8080
- 协议不同,如一个为
-
推荐方式2和方式4,方式1和方式3都不好控制,要想更好的控制需要自己实现
允许跨域的方式很多,比如vue的server proxy,nginx做代理,Java Web拦截器/过滤器等
坑点
- 测试过程中发现配置了允许跨域,chrome浏览器仍然报不允许跨域的提示,换edge却可以正常访问
2.配置origin时,origin配置的是你的来源方的域名,比如我在http://a.com 页面调用http://b.com/api ,那么origin应配置为http://a.com
方式1
直接在接口上添加
@CrossOrigin
注解
// @CrossOrigin
// @CrossOrigin(origins = "*")
// @CrossOrigin(origins = "https://www.doubao.com")
// @CrossOrigin(originPatterns = "https://www.doubao.com")
// @CrossOrigin(originPatterns = "https://www.doubao.com:[*]")
@CrossOrigin(originPatterns = "https://*.doubao.com:[*]")
@PostMapping("/test")
public Demo test(@RequestBody Map<String, Object> param) {
return null;
}
方式2(推荐)
package org.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 和allowedOrigins("*")不能同时配置allowCredentials(true),配置了allowedOrigins("*")就不能配置allowCredentials(true)
// allowCredentials(true)要求配置明确的跨域源
// 不同浏览器存在缓存还是什么机制,如下配置在chrome浏览器会跨域,edge却正常
registry.addMapping("/**")
// .allowedOrigins("*")
// 精准指定
.allowedOrigins("https://www.doubao.com")
// 通配符指定
// .allowedOriginPatterns("https://*.doubao.com")
// .allowedOriginPatterns("https://www.doubao.com:[*]")
// .allowedMethods("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("Content-Type", "Authorization", "Access-Control-Allow-Origin")
.allowCredentials(true)
.maxAge(3600);
}
}
方式3
自定义过滤器
package org.example.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Set;
/**
* @author admin
*/
@Slf4j
@Component
@WebFilter(urlPatterns = "/*")
public class CustomCorsFilter implements Filter {
private final Set<String> METHODS = Set.of("GET", "POST", "PUT", "DELETE", "OPTIONS");
private final String METHOD = String.join(",", METHODS);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("doFilter ...");
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String method = req.getMethod();
if (method == null) {
return;
}
if (!METHODS.contains(method)) {
return;
}
log.info("doFilter ... Request Method: {}", method);
log.info("Request Headers: {}", req.getHeaderNames());
log.info("header: {}:{}", HttpHeaders.ORIGIN, req.getHeader(HttpHeaders.ORIGIN));
// 设置允许跨域的域名,* 表示允许所有域名
resp.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "https://www.doubao.com");
// resp.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, CorsConfiguration.ALL);
// 设置允许的请求方法
resp.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, METHOD);
// 设置允许的请求头
resp.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, HttpHeaders.CONTENT_TYPE);
resp.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
// 允许携带凭证(如 cookie)
resp.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.TRUE.toString());
if (HttpMethod.OPTIONS.matches(req.getMethod())) {
log.info("doFilter OPTIONS");
resp.setStatus(HttpServletResponse.SC_OK);
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
}
方式4(推荐)
添加配置类注入web自带的跨域过滤器CorsFilter
package org.example.filter;
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;
import java.util.List;
/**
* @author admin
*/
@Configuration
public class MyCorsFilter {
@Bean
public CorsFilter corsFilter() {
System.out.println("filter......");
// 配置跨域规则
CorsConfiguration config = new CorsConfiguration();
// 允许所有来源
config.addAllowedOriginPattern("*");
// 允许所有请求方法
// config.addAllowedMethod("*");
config.setAllowedMethods(List.of("GET", "PUT", "DELETE", "OPTIONS"));
// 允许所有请求头
config.addAllowedHeader("*");
// 允许携带凭证(如 cookie)
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 对所有接口都有效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}