【问题标题】:Angular 6 with Spring security webflux blocked by CORS带有 Spring 安全 webflux 的 Angular 6 被 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请求吗?

标签: angular spring-boot spring-security spring-webflux


【解决方案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 标头时。

参考资料:

【讨论】:

    【解决方案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

    【讨论】:

      猜你喜欢
      • 2021-08-17
      • 2020-06-15
      • 2019-05-05
      • 2017-12-20
      • 2018-10-18
      • 2022-01-24
      • 2019-06-26
      • 2021-01-06
      • 2020-10-24
      相关资源
      最近更新 更多