为什么/ login?logout重定向到/ login?

YLo*_*rdi 10 java spring spring-security

在我的Spring项目中,我将注销目标URL设置为"/ login?logout"以显示登录页面,并显示消息"您现在已注销".

在Spring Security配置中,我这样做了:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/error").permitAll()
            .anyRequest().fullyAuthenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .successHandler(loginSuccessHandler)
            .failureUrl("/login?error")
            .and()
            .httpBasic()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .permitAll()
            .logoutSuccessHandler(logoutSuccessHandler);
}
Run Code Online (Sandbox Code Playgroud)

和logoutSuccessHandler:

public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException, ServletException {

    if (authentication != null) {
        Log.debug(authentication.getName() + " LOGOUT !!");
    }

    setDefaultTargetUrl("/login?logout");
    super.onLogoutSuccess(request, response, authentication);       
}
Run Code Online (Sandbox Code Playgroud)

当我尝试注销时,我到达页面"/ login"(没有?logout).我不明白为什么它会在这个页面上重定向我.

我认为该应用程序试图将我重定向到"/ login?logout",但由于我不再连接,Spring安全性要求我再次登录.

当我在登录时尝试访问"/ login?logout"页面时,它会显示正常页面.

我通过添加以下内容找到了解决此问题的方法:

            .authorizeRequests()
            .antMatchers("/error","/login").permitAll()
Run Code Online (Sandbox Code Playgroud)

为什么不loginPage("/login").permitAll()这样做?我做错什么了吗?

hee*_*nee 15

为什么 loginPage("/login").permitAll() 不允许访问 /login?logout

因为当你permitAll在一个FormLoginConfigurer或大多数其他配置器上执行此操作时,它只允许访问这些确切的URL.

那么,为什么 authorizeRequests().antMatchers("/login").permitAll() 允许访问呢?

因为它使用仅在请求路径上匹配的 an AntPathRequestMatcher,并且路径不包含查询字符串.

但我知道我已经看过代码,让我可以在 /login?logout 没有任何明确的情况下 访问permitAll .那是怎么回事?

Spring Security喜欢提供"合理的"默认值,并且如果没有指定默认登录和注销页面,它认为提供默认登录和注销页面是"明智的".默认的注销页面是/login?logout,如果您不指定任何内容,则可以使用它.这是通过DefaultLoginPageGeneratingFilter自动生成一些HTML和短路URL授权来完成的.

那么 /login?logout 当我指定一个时, 为什么我会失去对默认页面的访问权限logoutSuccessHandler

当您指定自己的logoutSuccessHandler或者logoutSuccessUrl,Spring Security假定您提供自己的注销视图,因此它不会DefaultLoginPageGeneratingFilter在注销页面上初始化到短路URL授权,并且您希望自己在自己的视图上配置授权.

但我想保留默认的注销页面.我只是想添加一些自定义的额外处理.我不能这样做吗?

如果您想指定自己的logoutSuccessHandler但仍保留默认/login?logout视图,则必须告诉DefaultLoginPageGeneratingFilter仍然继续提供它.您可以使用自定义执行此操作SecurityConfigurer,如下所示:

.logoutSuccessHandler(logoutSuccessHandler)
.and()
.apply(new SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>() {
    @Override public void configure(HttpSecurity builder) throws Exception {
        builder.getSharedObject(DefaultLoginPageGeneratingFilter.class).setLogoutSuccessUrl("/login?logout");
    }
})
Run Code Online (Sandbox Code Playgroud)