执行登录保存请求后,Spring Boot Security POST 重定向到登录页面

Posted

技术标签:

【中文标题】执行登录保存请求后,Spring Boot Security POST 重定向到登录页面【英文标题】:Spring Boot Security POST redirects to LoginPage, after Login Save Request executes 【发布时间】:2019-11-05 15:23:26 【问题描述】:

我面临着非常烦人的问题,我不知道如何处理它。我正在登录我的应用程序,导航效果很好,登录/注销效果很好。但是当我想在某个地方保存一些东西时,我会被直接重定向到 LoginPage。在日志中,只有我的 LoginController 被执行。当我再次登录时,我的 POST 请求就会执行,数据是安全的。我在应用程序中到处都有这种行为,我认为这在某种程度上是 Spring Security 的配置问题。非常欢迎任何帮助。

我的 Spring 安全配置:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    final FormLoginConfigurerEnhancer enhancer;
    final AuthenticationSuccessHandler authenticationSuccessHandler;

    @Override
    public void configure(WebSecurity web) throws Exception 
    web.ignoring().antMatchers("/webjars/**", "/css/**", "/js/**", "/images/**");
     

    @Override
    public void configure(HttpSecurity http) throws Exception 
        enhancer.addRecaptchaSupport(http.formLogin())
            .loginPage("/login")
                .successHandler(authenticationSuccessHandler)
                .and()
                .csrf().disable()
            .authorizeRequests()
                .antMatchers("/", "/login", "/home", "/registration").permitAll()
                .anyRequest().authenticated()
        ;
    

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) throws Exception 
        auth.userDetailsService(userDetailsService);
    

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    

似乎当我保存(发布)某些内容时,我的用户是匿名的。这是日志的一部分,当我按下保存按钮时:

2019-06-23 19:14:22.373 DEBUG 21576 --- [io-8080-exec-10] os.s.w.a.i.FilterSecurityInterceptor :以前经过身份验证:org.springframework.security.authentication.AnonymousAuthenticationToken@bffd4a17:主体:anonymousUser;凭证:[受保护];已认证:真实;详细信息:org.springframework.security.web.authentication.WebAuthenticationDetails@b364:RemoteIpAddress:0:0:0:0:0:0:0:1;会话ID:空;授予权限:ROLE_ANONYMOUS 2019-06-23 19:14:22.373 调试 21576 --- [io-8080-exec-10] ossaccess.vote.AffirmativeBased:投票者:org.springframework.security.web.access.expression.WebExpressionVoter@47fca1e0,返回:-1 2019-06-23 19:14:22.373 调试 21576 --- [nio-8080-exec-6] o.s.s.w.a.ExceptionTranslationFilter :访问被拒绝(用户是匿名的);重定向到身份验证入口点

我还发现,请求会话 ID 已变为无效:

2019-06-23 19:22:29.874 DEBUG 21576 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy : /property/edit 在附加过滤器链中的 11 位置 9;触发过滤器:'SessionManagementFilter' 2019-06-23 19:22:29.874 DEBUG 21576 --- [nio-8080-exec-9] os.s.w.session.SessionManagementFilter:请求的会话 ID 9FBCB80752CBCFC16D704D6C3BB62E05 无效。

我使用的是 Spring Boot 最新的 2.1.6 版本。

【问题讨论】:

【参考方案1】:

我找到了解决问题的方法。但这更像是一种解决方法,不知道为什么它现在有效,但以前无效。所以我在这里写下我是如何工作的答案,但仍然欢迎任何背景知识或更好的解决方案。

主要问题是,当我发送一个保存内容的帖子时,我被 Spring Security 注销。所以我在 Spring Security 方法中使用了.logout

我的注销 URL 应该是 /login?logout。 Spring Boot 不知何故有一个默认 URL 为/logout。但是我必须手动设置 logoutUrl 才能使我的保存功能正常工作。所以现在我将它定义为.logoutUrl("/login?logout"),然后保存就可以了。 (当我删除它并保存一些东西时,我会退出!)

所以我的 Spring Security 现在配置如下:

@Override
public void configure(HttpSecurity http) throws Exception 
    enhancer.addRecaptchaSupport(http.formLogin())
        .loginPage("/login")
            .successHandler(authenticationSuccessHandler)
            .and()
            .csrf().disable()
            .logout().logoutUrl("/login?logout")
            .and()
        .authorizeRequests()
            .antMatchers("/", "/login", "/home", "/registration").permitAll()
            .anyRequest().authenticated()
    ;

我仅使用.logoutUrl("/login?logout") 配置了 Spring Security,以使我的应用程序能够保存并且不会被注销。当我想注销时,我被重定向到错误的 spring 默认 url /logout。所以我现在在我的LoginController 中定义了一个方法来重定向到正确的 url。

@PostMapping("/logout")
public ModelAndView logout() 
    return new ModelAndView("redirect:/login?logout");

这一切都超级丑陋和令人困惑,但我真的不知道这里发生了什么。请把光明投入黑暗。非常感谢

【讨论】:

以上是关于执行登录保存请求后,Spring Boot Security POST 重定向到登录页面的主要内容,如果未能解决你的问题,请参考以下文章

登录后 Spring Boot 重定向到请求的 URL

为啥我登录后无法进入管理 REST API 请求映射 - Spring Boot

在 N 个并行保存请求后 Spring Boot Rest Api 卡住了

thymeleaf sec:授权在 Spring Boot 中不工作

spring boot 实例之 用户登录

spring boot 使用redis 管理用户会员登录