【问题标题】:Spring Boot Preflight request doesn't pass access control checkSpring Boot Preflight 请求未通过访问控制检查
【发布时间】:2020-10-20 09:21:36
【问题描述】:

我在我的 Web 应用程序中使用 Spring Boot 和 Spring Security。现在我有一个 /api/login 端点,前端只需在请求正文中发布用户名和密码即可获取 JWT。

但我不断得到

Access to fetch at 'http://localhost:8081/api/login' from origin 'http://localhost:3001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

我已经在控制器类上添加了 @CrossOrigin(origins = "*",maxAge = 3600) 来解决 cors 问题,所以现在 http get 工作正常。但是由于预检,所有帖子都不起作用。我也试过了

.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()

.and().cors();

在我的 WebSecurityConfigurerAdapter 中,但没有一个能解决问题。接下来我该怎么做?

这是完整的配置类:

package com.cyf.myblogserver.config;

import com.cyf.myblogserver.component.JwtRequestFilter;
import com.cyf.myblogserver.service.BlogUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private BlogUserDetailsService BlogUserDetailsService;
    @Autowired
    JwtRequestFilter jwtRequestFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(BlogUserDetailsService);
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .antMatchers(HttpMethod.POST,"/api/token").permitAll()
                .antMatchers(HttpMethod.GET, "/api/articles").permitAll()
                .anyRequest().authenticated().and().cors();
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        http.headers().cacheControl();
    }

    @Bean
    public AuthenticationManager customAuthenticationManager() throws Exception {
        return authenticationManager();
    }
}

【问题讨论】:

    标签: spring-boot spring-security


    【解决方案1】:

    如果您使用的是 spring security,请为您的 cors 进行全局设置,例如:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception { 
             http.
             cors().and().csrf().disable()
                    .authorizeRequests()                                                                
                    .antMatchers("/**").permitAll()
                    .antMatchers("/login").hasRole("ADMIN")                                      
                    .antMatchers("/Signup").hasRole("USER")
                    .and() //add rest of your configurations
        }
    
        @Bean   
        public CorsConfigurationSource corsConfigurationSource() {
            CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(Arrays.asList("http://localhost:3001")); //or add * to allow all origins
            configuration.setAllowCredentials(true);
            configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); //to set allowed http methods
            configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
            configuration.setExposedHeaders(Arrays.asList("custom-header1", "custom-header2"));
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration); 
            return source; 
        }
    }
    

    当您在全局范围内提供这样的配置时,代码会更加简洁,您也可以根据需要提供配置,它将适用于所有控制器及其方法。确保 spring 自动配置工作,我们提供 cors 配置 bean 并在 spring 安全性上启用 cors,因此如果自动配置工作,spring 将自动使用我们使用配置创建的 cors bean。

    【讨论】:

    • 谢谢,添加像你这样的全局配置可以解决问题!
    猜你喜欢
    • 2022-01-04
    • 2019-12-29
    • 1970-01-01
    • 2018-04-13
    • 2021-10-25
    • 2017-04-04
    • 2018-07-04
    • 2016-06-05
    相关资源
    最近更新 更多