关于Spring Security的CORS

目录

一、CORS是什么

二、同源安全策略

[三、Spring Security中CORS的开启](#三、Spring Security中CORS的开启)

四、其它处理方法


一、CORS是什么

CORS(Cross-Origin Resource Sharing,跨源/域资源共享 )是一个W3C标准,一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本(比如AJAX)请求访问的机制,通常由于同源安全策略,浏览器会禁止这种跨域请求。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附件的头信息,有时还会多处一次附件的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS功能(响应报文包括了正确的CORS响应头),就可以被跨源访问(可以指定个别域或全部域)。

二、同源安全策略

说到跨域请求,就不得不说一下"同源安全策略"了,如果没有这个策略的存在,也就没有这么多事了,但是,这样可能会造成你在网站进行一些操作时存在风险。

同源策略是一个重要的安全策略,它用于限制一个源/域的文档或它加载的脚本是否能与另一个源/域的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

出于安全性,浏览器会限制脚本内发起的跨域HTTP请求,例如常见的 XHR、Fetch API 都遵循同源策略。

如果两个 URL 的协议(Protocol)、主机(Host)、端口(Port,如果有指定的话)都相同的话,那么这两个 URL 是同源的,否则是不同源的。

当浏览器中打开的某个网页,有脚本执行了跨域请求,那么,浏览器的"同源安全策略"就会介入,大致流程如下:

浏览器直接发出CORS请求,也就是在头信息之中,增加一个Origin字段。这个字段代表本次请求来自哪个源(协议 + 主机 + 端口),服务器会根据这个值,决定是否同意这次请求。前面的流程是对于HTTP简单请求,如果是HTTP非简单请求,则会在正式请求前,增加一次预检请求。

如果Origin指定的源,不在许可范围内(服务器端CORS功能指定),服务器会返回一个正确的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态识别,因为HTTP回应的状态码有可能是 200

抛出的错误为"has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.",如下:

三、Spring Security中CORS的开启

在Spring框架中,我们可以在引入Spring Security依赖后,对Security的HttpSecurity进行设置,来开启CORS(跨域/源资源共享),同时能指定只被部分域/源、部分方法、部分头部信息访问资源。

Spring框架提供了CorsFilter,是为了在基于filter的安全框架(如Spring Security)上面支持CORS,或者在使用其他不支持CORS的库上支持CORS。

java 复制代码
//(Security6.2.4写法)先创建一个普通JAVA类,如SecurityConfig.java,实现如下3个Bean。
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                (authz) -> authz
                        .anyRequest().authenticated())
            .httpBasic(withDefaults())
            .formLogin(withDefaults())
            .csrf((csrf)->csrf.disable())
            .cors(withDefaults()); //开启CORS(跨域/源资源共享)
        return http.build();
    }

    @Autowired //自动装配参数configurationSource(下方的Bean)
    @Bean
    public CorsFilter corsFilter(UrlBasedCorsConfigurationSource configurationSource){
        return new CorsFilter(configurationSource);
    }

    // 也可以将方法内的实现整合到上面的corsFilter方法体内
    @Bean
    public UrlBasedCorsConfigurationSource configurationSource(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOriginPattern("http://localhost*"); //新版本写法
        //corsConfiguration.addAllowedOrigin("*"); //老版本写法
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }

四、其它处理方法

1、Spring注解

原理:自Spring Framework 4.2开始,CORS请求(包括OPTIONS method)会被自动分发到各种注册过的HandlerMappings。它们会处理CORS的preflight请求,会拦截CORS简单和实际请求,以便基于你指定的CORS配置,添加相关的CORS响应头(如 Access-Control-Allow-Origin)。

实现:在@RequestMapping注解过的controller method上面添加@CrossOrigin注解,表示已开启CORS。

java 复制代码
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600) //括号内为指定的CORS配置
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://domain2.com") //同时使用controller级别和method级别的CORS配置,Spring会将二者的attributes结合起来,创建出融合的CORS配置。
    @RequestMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
}

除了基于注解@CrossOrigin的配置(细粒度),还可以定义全局的CORS配置。类似于使用filters,但可以定义在Spring MVC中,并与细粒度的@CrossOrigin配置相配合。

2、JSONP(JSON with Padding)

原理:利用<script>标签不受浏览器同源策略限制的特性,通过动态插入<script>标签的方式实现跨域数据访问。

实现:客户端创建一个<script>标签,将请求后端的接口URL拼接一个回调函数名称作为参数传给后端,并设置给<script>标签的src属性。后端接收到请求后,将数据和回调函数名称拼接成函数调用的形式返回。客户端在接收到响应后,会执行这个回调函数,从而获取到后端返回的数据。

3、使用代理服务器

原理:通过搭建一个代理服务器来转发客户端的请求,代理服务器与目标服务器进行通信,然后将返回的数据再转发给客户端。由于客户端和代理服务器、代理服务器和目标服务器之间的通信都在服务器端进行,因此不受浏览器同源策略的限制。

实现:可以使用Nginx、Node.js等搭建代理服务器。例如,Nginx可以通过配置反向代理来解决跨域问题;Node.js可以搭建一个中间层服务器,接收客户端的请求,然后将请求转发给目标服务器,并将返回的数据再转发给客户端。

4、前端正向代理

原理:在客户端设置一个代理服务器,并指定目标服务器。代理服务器向目标服务器转交请求,并将获得的内容发送给客户端。这种方式在客户端进行了请求转发,但同样实现了跨域请求。

实现:可以通过在客户端代码中配置代理服务器地址和端口,以及目标服务器的地址和端口来实现。在发送请求时,将请求地址替换为代理服务器的地址,并在代理服务器中进行请求转发。

5、配置浏览器插件或工具

有些浏览器插件或工具(如Postman、curl等)可以绕过浏览器的同源策略限制,直接发送跨域请求。但这种方法主要用于开发和测试阶段,不建议在生产环境中使用。

相关文章:关于Spring Security的CSRF

相关推荐
钱多多_qdd10 分钟前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭11 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
李小白6611 小时前
Spring MVC(上)
java·spring·mvc
Lojarro13 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
zjw_rp14 小时前
Spring-AOP
java·后端·spring·spring-aop
撒呼呼17 小时前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
天使day18 小时前
SpringMVC
java·spring·java-ee
壹佰大多20 小时前
【spring-cloud-gateway总结】
java·spring·gateway