繁体   English   中英

由于 CORS,Spring 安全注销无法正常工作

[英]Spring security logout not working because of CORS

技术:后端的 Spring Security、Spring Boot 和前端的 ReactJs 和 axios。

我想要什么:在我的前端点击logout按钮时,我想注销用户。 为此,我使用delete调用后端。 然后我希望我的后端注销。

我的问题:当我从前端调用 Spring Security logout端点时,我收到以下消息: Failed to load http://localhost:8080/logout: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access. The response had HTTP status code 403. Failed to load http://localhost:8080/logout: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access. The response had HTTP status code 403. Failed to load http://localhost:8080/logout: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access. The response had HTTP status code 403.我明白为什么会出现此错误 - 后端在 localhost:8080 上,前端在 localhost:8888 上。 但我明白的是为什么我的配置不适用于注销,而它在所有其他情况下都可以正常工作(例如调用 spring 安全login端点或我的一些自定义端点)。

我如何从前端拨打电话

const endpoint = 'logout';
return axios.delete(
    'http://localhost:8080/' + `${endpoint}`,
    {withCredentials: true}
)
    .then(response => {
        let resp = {
            httpCode: response.status,
            data: response.data
        };
        return {response: resp};
    })
    .catch(error => {
        let err = {
            httpStatusCode: error.response.status,
            message: `Error calling endpoint ${endpoint}`
        };
        return {error: err};
    });

从前端启用 CORS

@Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:8888");
            }
        };
    }

SecurityConfig.java - 在这里您可能会注意到某些部分被注释了 - 它们是我尝试过的其他解决方案,但它们没有用。

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UsersRepository.class)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private RESTAuthenticationEntryPoint restAuthenticationEntryPoint;
    @Autowired
    private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
    @Autowired
    private RESTAuthenticationFailureHandler restAuthenticationFailureHandler;
    @Bean
    public CustomLogoutHandler customLogoutHandler(){
        return new CustomLogoutHandler();
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("**/anna/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .logout()
                .addLogoutHandler(customLogoutHandler())
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
        http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
        http.formLogin().successHandler(restAuthenticationSuccessHandler);
        http.formLogin().failureHandler(restAuthenticationFailureHandler);

//        http
//                .logout()
//                .logoutUrl("/logout")
//                .addLogoutHandler(new CustomLogoutHandler())
//                .invalidateHttpSession(true);

//        http
//                .cors()
//                .and()
//                .csrf().disable()
//                .logout()
//                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
    }

    private PasswordEncoder getPasswordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return true;
            }
        };
    }
}

CustomLogoutHandler.java我在某处阅读了有关在此处设置标题的解决方案。 我想这是不好的做法,不想这样做,但基本上我很高兴看到日志工作。 目前它没有记录任何内容,所以我猜它在注销时没有被调用。

//@Slf4j
public class CustomLogoutHandler implements LogoutHandler{
    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
        response.setHeader("Access-Control-Allow-Origin", "*");
        System.out.println("TodosLogoutHandler logging you out of the back-end app.");
    }
}

我检查了CorsRegistration的源代码,

public CorsConfiguration applyPermitDefaultValues() {
        [...]
        if (this.allowedMethods == null) {
            this.setAllowedMethods(Arrays.asList(
                    HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
        }
        [...]
        return this;
    }

如您所见,默认情况下不允许使用Delete方法,因此您需要添加delete方法。

@Bean
public WebMvcConfigurer corsConfigurer() {
  return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                            .allowedOrigins("http://localhost:8888")
                            .addAllowedMethod(HttpMethod.DELETE);
            }
        };
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM