万博:springboot后端如何优雅处理跨域CORS的三种方案

117 阅读2分钟

1、为什么会出现跨域

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。

同源策略是浏览器安全的基石。若地址里面的协议、域名和端口号均相同则属于同源。

http的请求url一般格式:协议+域名(子域名+主域名)+端口号+资源地址 所以只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。

2、解决跨域分析

CORS全称为Cross Origin Resource Sharing(跨域资源共享),

每一个页面需要返回一个名为 Access-Control-Allow-Origin的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。

我们可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置。

我们先来了解几个和cors相关的属性

Access-Control-Allow-Origin: www.toutiao.com

Access-Control-Allow-Methods: GET,POST,PUT,DELETE

Access-Control-Allow-Headers: X-Custom-Header

Access-Control-Allow-Credentials: true

Access-Control-Max-Age: 1800

它们的含义分别是

Access-Control-Allow-Origin:

Access-Control-Allow-Methods: 真实请求允许的方法

Access-Control-Allow-Headers: 服务器允许使用的字段

Access-Control-Allow-Credentials: 是否允许用户发送、处理 cookie Access-Control-Max-Age: 预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求

故此我们可以通知配置以上属性值来解决跨域的问题。

3、解决方案

方案一:使用@CrossOrigin注解

// 所有域名可以访问

@CrossOrigin

// 指定域名访问

@CrossOrigin("www.toutiao.com")

@RestController

public class TestController {

@GetMapping("/test")
public String test() {
    return "ok";
}

}

方案二:CORS全局配置

@Configuration

public class CorsConfiguration implements WebMvcConfigurer {

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").
                    // 允许跨域的域名,可以用*表示允许任何域名使用
                            allowedOrigins("https://www.toutiao.com").
                    // 允许任何方法(post、get等)(可以按需指定)
                            allowedMethods("*").
                    // 允许任何请求头(可以按需指定)
                            allowedHeaders("*").
                    // 带上cookie信息
                            allowCredentials(true).
                    exposedHeaders(HttpHeaders.SET_COOKIE)
                    // maxAge(1800)表明在1800秒内,不需要再发送预检验请求,可以缓存该结果
                    .maxAge(1800L);
        }
    };
}

}

方案三:拦截器Filter实现

@Component public class CorsFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpServletResponse res = (HttpServletResponse) response;
    res.addHeader("Access-Control-Allow-Credentials", "true");
    res.addHeader("Access-Control-Allow-Origin", "*");
    res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
    res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
    chain.doFilter(request, response);
}

@Override
public void destroy() {
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

}