java - 为什么/login?logout 会重定向到/login?

标签 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);
}

还有 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);       
}

当我尝试注销时,我到达了“/login”页面(没有 ?logout)。 我不明白为什么它会在此页面上重定向我。

我认为应用程序正在尝试将我重定向到“/login?logout”,但由于我不再连接,Spring 安全性希望我再次登录。

当我在登录时尝试访问“/login?logout”页面时,它会显示正确的页面。

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

            .authorizeRequests()
            .antMatchers("/error","/login").permitAll()

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

最佳答案

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

因为当您在 FormLoginConfigurer 或大多数其他配置器上执行 permitAll 时,它只允许访问那些 exact URLs .

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

因为它使用了一个AntPathRequestMatcher,它matches on the request path only , 和路径 does not contain the query string .

但我知道我已经看到了允许我访问的代码 /login?logout 没有任何明确的 permitAll 完全没有。这是怎么回事?

Spring Security 喜欢提供“合理的”默认值,如果没有指定默认登录和注销页面,它认为提供默认的登录和注销页面是“合理的”。默认的注销页面是/login?logout,所以如果你什么都不指定,你就可以使用它。这是由 DefaultLoginPageGeneratingFilter 完成的,它会自动生成一些 HTML 和 short-circuits URL authorization .

那么当我指定一个 logoutSuccessHandler时,为什么我无法访问默认页面 /login?logout 页面?

当您指定自己的 logoutSuccessHandlerlogoutSuccessUrl 时,Spring Security 假定您提供自己的注销 View ,因此它不会初始化 DefaultLoginPageGeneratingFilter 用于在注销页面短路 URL 授权,并希望您自己在自己的 View 上配置授权。

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

如果您想指定自己的 logoutSuccessHandler 但仍保留默认的 /login?logout View ,则必须告诉 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");
    }
})

关于java - 为什么/login?logout 会重定向到/login?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33167609/

相关文章:

java - 如何将 json 转换为 Map<String, Object> 确保整数为 Integer

java - 什么测试用例可以打破这个包含/排除原则挑战的解决方案?

java - 使用 ThreadPoolExecutor 在同一线程中的 Runnable 实例之间共享数据

spring - 使用Spring AMQP Java配置为每个队列配置专用的监听器容器

spring - 为什么我的 session 还活着

java - 应用程序在后台访问http

spring - Camel 化 Spring 启动应用程序

Spring-Security OAuth2 设置 - 无法找到 oauth2 命名空间处理程序

java - 如果我禁用授权,如何在测试中模拟安全上下文

java - JMS TextMessage、JMS_BEA_SELECT 消息选择器、事务处理 session 和确认模式