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

一. 启用Spring Security 的CORS支持

1. 普通的跨域
方式1:在接口方法上利用@CrossOrigin注解解决跨域问题
@RestController
public class IndexController {

    @CrossOrigin(value = "http://localhost:8082")
    @GetMapping("/hello")
    public String hello() {

        return "get hello";
    }

    @CrossOrigin(value = "http://localhost:8082")
    @PostMapping("/hello")
    public String hello2() {

        return "post hello";
    }
}
方式2:通过实现WebMvcConfigurer接口来解决跨域问题
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8082")
                .allowedMethods("*")
                .allowedHeaders("*");
    }

}

二. 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. 解决Spring Security环境下跨域问题的4种方案

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

2.1 方式一:开启cors方法

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

public class SecurityConfig extends WebSecurityConfigurerAdapter {

 @Override
 protected void configure(HttpSecurity http) throws Exception {
     http.authorizeRequests()
             .anyRequest()
             .permitAll()
             .and()
             .formLogin()
             .permitAll()
             .and()
             .httpBasic()
             .and()
             //支持跨域访问
             .cors()
             .and()
             .csrf()
             .disable();
 }

}
2.2 方式二:进行全局配置

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

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest()
                .permitAll()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .httpBasic()
                .and()
                //支持跨域访问
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf()
                .disable();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedMethods(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Collections.singletonList("*"));
        configuration.setMaxAge(Duration.ofHours(1));
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

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

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

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

/**
* 跨域配置方式3:定义全局跨域过滤器
**/
@Configuration
public class GlobalCorsConfiguration {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
    
}

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //跨域方式3:
        http.requestMatchers()
                .antMatchers(HttpMethod.OPTIONS, "/oauth/**")
                .and()
                .csrf()
                .disable()
                .formLogin()
                .and()
                .cors();
    }
}
2.4 方式4 :自定义一个全局跨域处理Filter
public class CorsFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        String orignalHeader = StringUtils.defaultIfBlank(request.getHeader("Origin"), "*");
        // 指定本次预检请求的有效期
        response.setHeader("Access-Control-Max-Age", "3600");
        // 服务器支持的所有头信息字段
        response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
        response.setHeader("Access-Control-Allow-Origin", orignalHeader);
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        filterChain.doFilter(request, response);
    }
}

public class WebMvcConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new CorsFilter (), WebAsyncManagerIntegrationFilter.class);
    }
}
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security 并不直接解决跨域问题,而是通过集成 Spring MVC 提供的跨域解决方案来处理。 在 Spring MVC ,可以通过添加 `@CrossOrigin` 注解来实现跨域访问。在 Spring Security ,可以通过配置 `WebSecurityConfigurerAdapter` 来添加 `CorsConfigurationSource`,从而实现跨域访问。 具体实现方法如下: 1. 在配置类添加 `CorsConfigurationSource`: ``` @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } // ... } ``` 2. 将 `CorsFilter` 添加到 Spring Security 过滤器链: ``` @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // ... @Override protected void configure(HttpSecurity http) throws Exception { http // ... .cors() .and() // ... } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } } ``` 这样就可以通过 Spring Security 实现跨域访问了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值