带有 Spring 安全 webflux 的 Angular 6 被 CORS 阻止

Posted

技术标签:

【中文标题】带有 Spring 安全 webflux 的 Angular 6 被 CORS 阻止【英文标题】:Angular 6 with Spring security webflux blocked by CORS 【发布时间】:2019-01-27 01:35:05 【问题描述】:

我正在尝试编写一个使用 Springs WebFlux Security 的应用程序。在前端 Angular 应用程序中,我将用户带到登录页面,一旦他们登录,应用程序应该重定向到不同的 uri。截至目前,我收到此错误:

     Failed to load http://localhost:8080/login: Redirect from 
     'http://localhost:8080/login' to 'http://localhost:8080/pets' has been 
     blocked by CORS policy: No 'Access-Control-Allow-Origin' header is 
     present on the requested resource. Origin 'http://localhost:4200' is 
     therefore not allowed access.

目前我不确定为什么会出现 CORS 错误,但这是我对 spring webflux 安全性的了解

@EnableWebFluxSecurity
public class SecurityConfig 

@Autowired
private ReactiveUserDetailsService reactiveUserDetailsService;

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) 
    http
            .authorizeExchange()
            .pathMatchers(HttpMethod.POST, "/login").permitAll()
            .pathMatchers(HttpMethod.POST, "/logout").permitAll()
            .pathMatchers(HttpMethod.POST, "/register").permitAll()
            .anyExchange().authenticated()
            .and()
            .httpBasic().disable()
            .csrf().disable()
            .formLogin()
            .authenticationManager(authenticationManager())
            .requiresAuthenticationMatcher(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, "/login"))
            .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/pets"))
            .authenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(new HttpBasicServerAuthenticationEntryPoint()))
            .authenticationEntryPoint(new HttpBasicServerAuthenticationEntryPoint())
            .and()
            .logout()
            .logoutSuccessHandler(((exchange, authentication) -> Mono.fromRunnable(() -> exchange.getExchange().getResponse().setStatusCode(HttpStatus.OK))));

    return http.build();


@Bean
public ReactiveAuthenticationManager authenticationManager() 
    UserDetailsRepositoryReactiveAuthenticationManager authManager =
            new UserDetailsRepositoryReactiveAuthenticationManager(reactiveUserDetailsService);

    authManager.setPasswordEncoder(passwordEncoder());
    return authManager;


@Bean
PasswordEncoder passwordEncoder() 
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();


我有什么遗漏或需要修改的吗?

【问题讨论】:

你确定你可以从4200端口向8080端口发起http请求吗? 【参考方案1】:

我遇到了这个问题,我正在使用这个组合:Spring Boot + Webflux + Security。

控制器 @CrossOrigin 不起作用 全球跨域,就像之前的答案中设置的那样,也不起作用

这里记录了唯一对我有用的解决方案:

Enable CORS in Spring 5 Webflux?

创建一个 SecurityConfiguration 类

使用这种组合使 CORS 工作的关键是 configuration.applyPermitDefaultValues();

如果您删除该行,它将不起作用

import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.http.HttpMethod;
  import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
  import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
  import org.springframework.security.config.web.server.ServerHttpSecurity;
  import org.springframework.security.web.server.SecurityWebFilterChain;
  import org.springframework.web.cors.CorsConfiguration;
  import org.springframework.web.cors.reactive.CorsConfigurationSource;
  import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

  import java.util.Arrays;

  @Configuration
  @EnableWebFluxSecurity
  @EnableReactiveMethodSecurity
  public class SecurityConfiguration 

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) 
      System.out.println("Security Config");

      http
              .csrf().disable()
              .cors().configurationSource( corsConfigurationSource() ).and()
              .authorizeExchange()
              .pathMatchers(HttpMethod.POST, "/auth", "/api").permitAll()
              .pathMatchers(HttpMethod.GET,"/**").permitAll()
              .anyExchange().authenticated();

      return http.build();
  

  @Bean
  CorsConfigurationSource corsConfigurationSource() 
      CorsConfiguration configuration = new CorsConfiguration();
      configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
      configuration.setAllowedMethods(Arrays.asList("GET","POST"));
      configuration.setMaxAge(3600L);
      configuration.applyPermitDefaultValues();
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", configuration);
      return source;
  

【讨论】:

我测试了其他解决方案,您链接的解决方案运行良好。但是,当您的 pom.xml 中存在 Spring Security 时,除了您的之外,其他解决方案将不起作用。感谢您分享这个解决方案。【参考方案2】:

您应该在 Spring 应用程序的配置中定义 CORS 映射。

这是我的示例:

@Configuration
@EnableWebFlux
@Import(CoreConfiguration.class, SecurityConfiguration.class)
public class ServicesConfiguration implements WebFluxConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 

        registry.addMapping("/api/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("Access-Control-Allow-Origin",
                        "Access-Control-Allow-Methods",
                        "Access-Control-Allow-Headers",
                        "Access-Control-Max-Age",
                        "Access-Control-Request-Headers",
                        "Access-Control-Request-Method")
                .maxAge(3600);

        // Add more mappings...
    

事实是,如果我测试来自 Postman 的请求,没有 CORS 问题,它会出现在前端(实际上是浏览器)需要适当的 CORS 标头时。

参考资料:

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html

https://github.com/spring-projects/spring-framework/blob/master/src/docs/asciidoc/web/webflux-cors.adoc

【讨论】:

【参考方案3】:

你做得完全正确,但你需要将你的端口 8080 配置为代理端口。

只需在项目的根目录中创建一个名为 proxy.conf.json 的新文件,并在其中定义您的代理,如下所示。


  "/login": 
     "target":  
       "host": "localhost",
       "protocol": "http:",
       "port": 8080
     ,
     "secure": false,
     "changeOrigin": true,
     "logLevel": "info"
  

同样你也可以绑定另一个 url。

现在在您运行 Angular 应用程序时进行下一步。执行以下命令。

ng 服务 --proxy-config proxy.conf.json

【讨论】:

以上是关于带有 Spring 安全 webflux 的 Angular 6 被 CORS 阻止的主要内容,如果未能解决你的问题,请参考以下文章

WebTestClient - 带有 Spring Boot 和 Webflux 的 CORS

带有 MultipartFile 的 Spring Webflux 415

带有 Spring WebFlux 的 RestController:必需参数不存在

Spring Security WebFlux - 带有身份验证的主体

Spring WebFlux 安全自定义 AccessDeniedHandler

如何在spring webflux安全中通过绕过选项请求?