Spring Security系列教程25--解决Spring Security环境中的跨域问题

简介: 前言上一章节中,一一哥 给各位讲解了同源策略和跨域问题,以及跨域问题的解决方案,在本篇文章中,我会带大家进行代码实现,看看在Spring Security环境中如何解决跨域问题。一. 启用Spring Security 的CORS支持1. 创建web接口我先在SpringBoot环境中,创建一个端口号为8080的web项目,注意这个web项目没有引入Spring Security的依赖包。然后在其中创建一个IndexController,定义两个测试接口以便被ajax进行跨域访问。@RestControllerpublic class IndexController {

前言

上一章节中,一一哥 给各位讲解了同源策略和跨域问题,以及跨域问题的解决方案,在本篇文章中,我会带大家进行代码实现,看看在Spring Security环境中如何解决跨域问题。

一. 启用Spring Security 的CORS支持

1. 创建web接口

我先在SpringBoot环境中,创建一个端口号为8080的web项目,注意这个web项目没有引入Spring Security的依赖包。然后在其中创建一个IndexController,定义两个测试接口以便被ajax进行跨域访问。

@RestControllerpublicclassIndexController {
@GetMapping("/hello")
publicStringhello() {
return"get hello";
    }
@PostMapping("/hello")
publicStringhello2() {
return"post hello";
    }
}

8080项目的代码结构:

请参考如下代码结构进行项目创建。

2. 执行ajax请求

我们接下来再创建另一个端口号为8082的web项目,注意这个web项目也没有引入Spring Security的依赖包。接着在这里定义一个index.html页面,利用ajax跨域访问8080项目中的web接口。

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>Index</title><scripttype="text/javascript"src="jquery-2.1.0.js"></script></head><body><divid="app"></div><inputtype="button"onclick="btnClick()"value="get请求"><inputtype="button"onclick="btnClick2()"value="post请求"><script>functionbtnClick() {
$.get('http://localhost:8080/hello', function (msg) {
$("#app").html(msg);
        });
    }
functionbtnClick2() {
$.post('http://localhost:8080/hello', function (msg) {
$("#app").html(msg);
        });
    }
</script></body></html>

8082项目的代码结构:

请参考如下代码结构进行项目创建。

3. 发起跨域请求

我们访问8082项目中的index.html页面,然后分别执行get与post请求,这时候就可以在浏览器的控制台上看到产生了CORS跨域问题,出现了CORS error状态,在请求头中出现了Referer Policy: strict-origin-when-cross-origin。

4. 解决跨域问题

既然现在产生了跨域问题,那么该怎么解决呢?其实我们可以采用如下两种方式之一来解决跨域问题。

方式1:在接口方法上利用@CrossOrigin注解解决跨域问题

@RestControllerpublicclassIndexController {
@CrossOrigin(value="http://localhost:8082")
@GetMapping("/hello")
publicStringhello() {
return"get hello";
    }
@CrossOrigin(value="http://localhost:8082")
@PostMapping("/hello")
publicStringhello2() {
return"post hello";
    }
}

方式2:通过实现WebMvcConfigurer接口来解决跨域问题

@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer {
@OverridepublicvoidaddCorsMappings(CorsRegistryregistry) {
registry.addMapping("/**")
                .allowedOrigins("http://localhost:8082")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

当进行了跨域设置之后,我们再次进行跨域请求,就可以看到请求成功了。

二. Spring Security环境下的跨域问题解决

1. 引入Spring Security依赖

通过上面的配置,我们已经解决了Ajax的跨域请求问题,但是这个案例中也有潜在的威胁存在,常见的就是 CSRF(Cross-site request forgery) 跨站请求伪造。跨站请求伪造也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF,是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。

所以为了提高网站的安全性,我在上面Spring Boot项目的基础之上,添加Spring Security的依赖包,但是暂时不进行任何别的操作。

 

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies>

2. 重启8080项目进行测试

接着我就重启8080这个Spring Boot项目,然后在8082项目中再次进行跨域请求,我们会发现在引入Spring Security后,再次产生了跨域问题。

3. 解决Spring Security环境下跨域问题的3种方案

通过实验可知,如果使用了 Spring Security,上面的跨域配置会失效,因为请求会被 Spring Security 拦截。那么在Spring Security环境中,如何解决跨域问题呢?这里我们有3种方式可以开启 Spring Security 对跨域的支持。

3.1 方式一:开启cors方法

我们在上面的案例之上,编写一个SecurityConfig配置类,在configure方法中,利用cors() 开启Spring Security 对 CORS 的支持:

@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .permitAll()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .httpBasic()
                .and()
//支持跨域访问                .cors()
                .and()
                .csrf()
                .disable();
    }
}

3.2 方式二:进行全局配置

第二种方式是去除上面的跨域配置,直接在 Spring Security 中做全局配置,如下:

@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .permitAll()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .httpBasic()
                .and()
//支持跨域访问                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf()
                .disable();
    }
@BeanpublicCorsConfigurationSourcecorsConfigurationSource() {
UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();
CorsConfigurationconfiguration=newCorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Collections.singletonList("*"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
configuration.setMaxAge(Duration.ofHours(1));
source.registerCorsConfiguration("/**", configuration);
returnsource;
    }
}

以上2个方法,都可以实现在Spring Security环境下的跨域访问。

3.3 方式三:支持OAuth2的跨域访问

我们开发时,还有一种情况就是支持 OAuth2 相关接口的跨域,比如用户要访问 OAuth2 中的 /oauth/token 等接口。我们可以配置一个全局的 CorsFilter 跨域过滤器类,核心代码如下:

/*** 跨域配置方式3:定义全局跨域过滤器**/@ConfigurationpublicclassGlobalCorsConfiguration {
@BeanpublicCorsFiltercorsFilter() {
CorsConfigurationcorsConfiguration=newCorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSourceurlBasedCorsConfigurationSource=newUrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
returnnewCorsFilter(urlBasedCorsConfigurationSource);
    }
}
@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
//跨域方式3:http.requestMatchers()
                .antMatchers(HttpMethod.OPTIONS, "/oauth/**")
                .and()
                .csrf()
                .disable()
                .formLogin()
                .and()
                .cors();
    }
}

该方式也可以实现Spring Security中的跨域访问。

4. 代码结构

以下是本案例的代码结构,可以参考下图进行项目创建:

至此,我就带各位解决了Spring Security环境中的跨域问题,你学会了吗?

相关文章
|
10月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1464 3
|
9月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
1701 5
|
11月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
1068 13
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
2023 3
|
存储 安全 Java
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(下)
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(下)
336 0
|
安全 Java 数据库
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(上)
第2章 Spring Security 的环境设置与基础配置(2024 最新版)
470 0
|
Java Nacos Spring
使用Spring Boot的Profile功能来实现不同环境使用不同的Nacos Namespace的配置
使用Spring Boot的Profile功能来实现不同环境使用不同的Nacos Namespace的配置
1139 1
|
Java 测试技术 Nacos
Spring Cloud Alibaba - 18 Nacos Config配置中心加载相同微服务的不同环境下的通用配置
Spring Cloud Alibaba - 18 Nacos Config配置中心加载相同微服务的不同环境下的通用配置
299 0
|
NoSQL Java 数据库连接
聊聊Spring的环境抽象Environment,以及配置@Profile使用详解(介绍profile的6种激活方式)【享学Spring】(下)
聊聊Spring的环境抽象Environment,以及配置@Profile使用详解(介绍profile的6种激活方式)【享学Spring】(下)
聊聊Spring的环境抽象Environment,以及配置@Profile使用详解(介绍profile的6种激活方式)【享学Spring】(下)