当前位置: 首页 > news >正文

SpringSecurity之跨域

跨域问题是实际应用开发中一个非常常见的需求,在Spring框架中对于跨域问题的处理方案有好几种,引入了Spring Security之后,跨域问题的处理方案又增加了。

1.什么是CORS

CORS(Cross-Origin Resource Sharing)是由W3C制定的一种跨域资源共享技术标准,其目的就是为了解决前端的跨域请求。在JavaEE开发中,最常见的前端跨域请求解决方案是早起的JSONP,但是JSONP只支持GET请求,这是一个很大的缺陷,而CORS则支持多种HTTP请求方法,也是目前主流的跨域解决方案。

CORS中新增了一组HTTP请求头字段,通过这些字段,服务器高炉浏览器,哪些网站通过浏览器有权限访问哪些资源。同时规定,对那些可能修改服务器数据的HTTP请求方法(如GET以外的HTTP请求等),浏览器必须首先使用OPTIONS方法发起一个预检请求(prenightst),预检请求的目的是查看服务端是否支持即将发起的跨域请求,如果服务端允许,才发送实际的HTTP请求。在预检请求的返回中,服务端也可以通知客户端,是否需要携带身份凭证(如Cookies、HTTP认证信息等)。

CORS: 同源/同域 = 协议 + 主机 + 端口

2.简单请求

GET请求为例,如果需要发起一个跨域请求,则请求头如下:

Host: localhost:8080 Origin: http://localhost:8081 Referer: http://localhost:8081/index.html

如果五段支持该跨域请求,那么返回的响应头中将包含如下字段:

Access-Control-Allow-Origin: http://localhost:8081

Access-Control-Allow-Origin字段用来告诉浏览器可以访问该资源的域,当浏览器收到这样的响应头信息之后,提取出Access-Control-Allow-Origin字段中的值,发现该值包含当前页面所在的域,就知道这个跨域是被允许的,因此就不再对前端的跨域请求进行限制。这属于简单请求,即不需要进行预检请求的跨域。

3.非简单请求

对于一些非简单请求,会首先发送一个预检请求。预检请求类似下面这样:

OPTIONS /put HTTP/1.1 Host: localhost:8080 Connection: keep-alive Accept: */* Access-Control-Request-Method: PUT Origin: http://localhost:8081 Referer: http://localhost:8081/index.html

请求方法是OPTIONS,请求头Origin就钙素服务端当前页面所在域,请求头Access-Control-Request-Methods告诉服务器端即将发起的跨域请求所使用的方法。服务端对此进行判断,如果允许即将发起的跨域请求,则会给出如下响应:

HTTP/1.1 200 Access-Control-Allow-Origin:http://localhost: 8081 Access-Control-Request-Methods: PUT Access-Control-Max-Age: 3600

Access-Control-Allow-Methods字段表示允许的跨域方法:Access-Control-Max-Age字段表示预检请求的有效期,单位为秒,在有效期内如果发起该跨域请求,则不用再次发起预检请求。预检请求结束后,接下来就会发起一个真正的跨域请求,跨域请求和前面的简单请求跨域步骤类似。

4.Spring跨域解决方案
4.1.@CrossOrigin

Spring中第一种处理跨域的方式是通过@CrossOrigin注解来标记支持跨域,该注解可以添加在方法上,也可以添加在Controller上。当添加在Controller上时,表示Controller中的所有接口都支持跨域,具体配置如下:

@RestController public class IndexController { @GetMapping("/hello") @CrossOrigin(origins = "http://localhost:8081") public String hello(){ System.out.println("hello ok"); return "hello ok"; } }

@CrossOrigin注解各属性含义如下:

  • allowCredentials:浏览器是否应当发送凭证信息,如Cookie。
  • allowedHeaders:请求被允许的请求头字段,*表示所有字段。
  • exposedHeaders:哪些响应头可以作为相应的一部分暴露出来。

注意,这里只可以一一列举,通配符 * 在这里是无效的。

  • maxAge:预检请求的有效期,有效期内不必再次发送预检请求,默认是1800秒
  • methods:允许的请求方法,*表示允许的所有方法。
  • origins:允许的域,*表示允许所有域。
4.2.addCrossMapping自定义mvc配置

@CrossOrigin注解需要添加在不同的Controller上。所以还有一种全局配置方法,就是通过重写WebMvcConfigurerComposite#addCorsMappings方法来实现,具体配置如下:

//自定义mvc配置类 @Configuration public class WebMvcConfig implements WebMvcConfigurer { //用来全局处理跨域 @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") //处理的请求地址 .allowedMethods("*") .allowedOrigins("*") .allowedHeaders("*") .allowCredentials(false) .exposedHeaders("") .maxAge(3600); } }
4.3.CorsFilter

CorsFilter是Spring Web中提供的一个处理跨域的过滤器,开发者也可以通过该过滤器处理跨域。

import org.springframework.boot.web.servlet.FilterRegistrationBean; 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 org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Arrays; /** * @author zhangKaiTao * @date 2022/7/24 10:30 */ //自定义mvc配置类 @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Bean FilterRegistrationBean<CorsFilter> corsFilter(){ FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedHeaders(Arrays.asList("*")); corsConfiguration.setAllowedMethods(Arrays.asList("*")); corsConfiguration.setAllowedOrigins(Arrays.asList("*")); corsConfiguration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**",corsConfiguration); registrationBean.setFilter(new CorsFilter(source)); registrationBean.setOrder(-1); return registrationBean; } }
5.SpringSecurity跨域解决方案

当我们为项目添加了Spring Security依赖后,发现上面三种跨域方式有的失效了,有的则可以继续使用,这是怎么回事?

通过@CrossOrigin注解或者重写addCorsMappings方法配置跨域,统统失效了,通过CorsFilter配置的跨域,有没有失效则要看过滤器的优先级,如果过滤器优先级高于SpringSecurity过滤器,即先于Spring Security过滤器执行,则CorsFilter所配置的跨域处理依然有效;如果过滤器优先级地域Spring Security过滤器,则CorsFilyer所配置的跨域处理就会失效。

以下是Filter、DispatcherServlet以及Interceptor执行顺序。

由于非简单请求都要首先发送一个预检请求(request),而预检请求并不会携带认证信息,所以预检请求就有被Spring Security拦截的可能。因此通过@CrossOrigin注解或者重写addCorsMappings方法配置跨域就会失效。如果使用CorsFilter配置的跨域,只要过滤器优先级高于SpringSecurity过滤器就不会有问题,反之同样会出现问题。

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { //... @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeHttpRequests() .anyRequest().authenticated() .and() .formLogin() .and() .cors().configurationSource(corsConfigurationSource()) .and() .csrf().disable();//开启csrf } CorsConfigurationSource corsConfigurationSource(){ CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedHeaders(Arrays.asList("*")); corsConfiguration.setAllowedMethods(Arrays.asList("*")); corsConfiguration.setAllowedOrigins(Arrays.asList("*")); corsConfiguration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**",corsConfiguration); return source; } }

http://www.jsqmd.com/news/454471/

相关文章:

  • 从0开始学习C++:C/C++ 输入输出全攻略
  • SpringMVC的工作流程
  • 国内信创实时云渲染服务商怎么选?靠谱标准看这几点
  • C++ 手写实现 unordered_map 和 unordered_set:深入解析与源码实战
  • 【Linux系统】进程状态 | 进程优先级
  • 中小企业布局信创实时云渲染,可行吗?
  • C++ 定长内存池,让内存分配快到飞起!
  • 信创实时云渲染与传统本地渲染,企业选型该瞄准哪些核心点?
  • 【毕业设计】SpringBoot+Vue+MySQL 医院信管系统平台源码+数据库+论文+部署文档
  • SpringBoot+Vue 智能菜谱推荐系统管理平台源码【适合毕设/课设/学习】Java+MySQL
  • C++ 异常处理机制详解:从基础语法到工程实践
  • 2026年江苏变压器铜铝排/变压器铜电磁线/变压器铝电磁线服务商采购白皮书:高压输配电领域的核心供应商竞争力解析 - 2026年企业推荐榜
  • Flutter 三方库 ntp_dart 的鸿蒙化适配指南 - 获取绝对可信的授时服务、助力鸿蒙端金融与考勤类应用杜绝本地时钟作弊风险
  • 【Linux系统】理解硬件 | 引入文件系统
  • 《Linux 输入输出重定向与 VI 编辑器:全面操作指南与原理剖析》
  • Spring推出Spring AI框架,看看怎么个事
  • 2026年无纸化会议系统推荐指南:会议音响套装/吸顶会议音箱/国产无纸化会议/多媒体室音响/大礼堂音响/选择指南 - 优质品牌商家
  • 【Linux系统】进程地址空间
  • Linux网络编程:应用层自定义协议与序列化
  • 2026年外贸建站公司实力大盘点:口碑、技术、信用TOP级企业全解析 - 品牌推荐大师1
  • 年度总结:我的技术成长与反思
  • 【Linux系统】命令行参数和环境变量
  • 核“芯”动力,重构无人机通信边界——LR1121IMLTRT 多频段LoRa收发器
  • Java项目中策略模式的使用方法:从零开始掌握可扩展业务逻辑设计
  • 互联网大厂Java小白面试:从基础到进阶的技术问答细节
  • 2026年快速温变试验箱优质供应商盘点:哪家能耗更低? - 品牌推荐大师
  • 2026年波纹金属软管厂商评价排行,目前评价好的波纹金属软管厂商选哪家,波纹补偿器/阀用波纹管,波纹金属软管品牌推荐 - 品牌推荐师
  • 零碳园区商业模式创新的政策支持对企业有哪些影响?
  • Linux服务器崩溃急救指南:实战演练常见故障排查
  • 互联网大厂Java面试:Spring Boot微服务与Redis缓存应用场景分析