【问题标题】:spring security - expiredUrl not working春季安全 - expiredUrl 不起作用
【发布时间】:2016-08-20 06:54:06
【问题描述】:

我需要在我的 Spring MVC 应用程序中配置 expired-url。这是我的努力,但没有效果:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(adminAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(customerAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers("...", "...", "...").permitAll()
            .anyRequest().authenticated()
        .and()
            .formLogin()
                .loginPage("/admin/login")
        .and()
            .logout()
                .addLogoutHandler(customLogoutHandler())
                .logoutSuccessHandler(customLogoutSuccessHandler())
                .logoutUrl("/logout")
        .deleteCookies("remove")
        .invalidateHttpSession(true)
            .permitAll()
        .and()
        .sessionManagement()
            .maximumSessions(1)
            .expiredUrl("/expired");

}

这没有任何影响,当用户的会话超时时,spring 不会将他重定向到/expired url,而只是将他重定向到/admin/login url。

更新:

我在 cmets and answer 中尝试了建议的解决方案,但没有看到任何效果。我还在方法的开头删除了addLogoutHandler()logoutSuccessHandler() 和两个addFilterBefore(),但没有工作。

我也以这种方式尝试了另一种解决方案:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(sessionManagementFilter(), SessionManagementFilter.class)
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers("...", "...", "...").permitAll()
            .anyRequest().authenticated()
        .and()
            .formLogin()
                .loginPage("/admin/login")
        .and()
            .logout()
                .logoutUrl("/logout")
        .deleteCookies("remove")
        .invalidateHttpSession(true)
            .permitAll();
}

@Bean
public SessionManagementFilter sessionManagementFilter() {
    SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(httpSessionSecurityContextRepository());
    sessionManagementFilter.setInvalidSessionStrategy(simpleRedirectInvalidSessionStrategy());
    return sessionManagementFilter;
}

@Bean
public SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy() {
    SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy("/expired");
    return simpleRedirectInvalidSessionStrategy;
}

@Bean
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository(){
    HttpSessionSecurityContextRepository httpSessionSecurityContextRepository = new HttpSessionSecurityContextRepository();
    return httpSessionSecurityContextRepository;
}

谁能帮我解决这个问题?

【问题讨论】:

  • @hamed, !Okay.. 我猜你没有必要的权限来访问/expired url(我知道这很尴尬,因为这是一个用于过期处理的 url),所以 spring 重定向你登录页面甚至访问过期页面..尝试没有痛苦..只需尝试添加.antMatchers("/expired","...",...).permitAll(),然后检查您现在是否成功重定向到过期页面或仍然是登录页面。如果它不起作用,请告诉我..

标签: java spring-mvc spring-security


【解决方案1】:

如果你使用UserDetailsUserDetailsService那应该是因为你的UserDetails实现类没有Override hashCode()和equals(Object obj)方法。这是我的 UserDetails 实现类:

public class MyUser implements UserDetails {
    private String username;

    private String password;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return null;
    }

    @Override
    public String getUsername() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

    @Override
    public int hashCode() {
        return username.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return this.toString().equals(obj.toString());
    }
}

【讨论】:

    【解决方案2】:

    我以这种方式尝试了 Ali Dehghani 的解决方案(在 cmets 中):

    .sessionManagement().maximumSessions(1).and().invalidSessionUrl("/expired");
    

    正如The Coder所说,在允许的网址中添加"/expired",问题就解决了。感谢所有关注我问题的人,特别是 Ali DehghaniThe Coder,感谢他们提供有用的 cmets。

    【讨论】:

      【解决方案3】:

      ConcurrentSessionFilter 将重定向到expiredUrl,如果valid 会话ID 在SessionRegistry 中标记为过期,请参阅Spring Security reference

      - expired-url 如果用户尝试使用由于用户超过允许的会话数而被并发会话控制器“过期”的会话,他们将被重定向到的 URL并在其他地方再次登录。除非设置了exception-if-maximum-exceeded,否则应该设置。如果未提供任何值,则将直接将过期消息写回响应。

      SessionManagementFilter会重定向到invalidSessionUrl,如果会话ID不是valid(超时或错误ID),见Spring Security reference

      如果用户当前未通过身份验证,过滤器将检查是否请求了无效的会话 ID(例如,由于超时),如果设置了 InvalidSessionStrategy,则会调用配置的 InvalidSessionStrategy。最常见的行为只是重定向到一个固定的 URL,这被封装在标准实现 SimpleRedirectInvalidSessionStrategy 中。后者也用于通过命名空间配置无效会话 URL,如前所述。

      两个网址(expiredUrlinvalidSessionUrl)都必须配置为permitAll()

      顺便说一句:如果您想将Concurrent Session ControlmaximumSessions 一起使用,您必须将HttpSessionEventPublisher 添加到您的web.xml

      并发会话控制

      如果您希望限制单个用户登录到您的应用程序的能力,Spring Security 通过以下简单的补充支持开箱即用。首先,您需要将以下侦听器添加到您的 web.xml 文件中,以使 Spring Security 更新有关会话生命周期事件的信息:

      <listener>
          <listener-class>
                 org.springframework.security.web.session.HttpSessionEventPublisher
          </listener-class>
      </listener>
      

      【讨论】:

        【解决方案4】:

        理想情况下,您的用户体验应该简单地将您的用户重定向回登录页面。我猜你看到有一个专用的 /expired 页面的要求,因为Spring MVC - change security settings dynamically 你通知了你需要有单独的登录掩码。如果解决方法(我在对您的另一个问题的回答中描述的解决方法)对您有用,您可能会放弃拥有专用/过期页面的要求,并使用解决方案方法编号直接将用户重定向到正确的登录页面( 2)。怎么样?

        不过,要回答您当前的问题... 我不确定它是否有效,但尝试一下并更改您的代码

                //...
                .sessionManagement()
                .maximumSessions(1)
                .expiredUrl("/expired");
            }
        

                //...
                .sessionManagement().sessionFixation().newSession().maximumSessions(1)
                .expiredUrl("/expired")
                .sessionRegistry(sessionRegistry());
            }
        
            @Bean
            public SessionRegistry sessionRegistry() {
                SessionRegistry sessionRegistry = new SessionRegistryImpl();
                return sessionRegistry;
            }
        

        如果它不起作用,您能否发布您的customLogoutHandler()customLogoutSuccessHandler() 的代码?您在 Spring Boot 之外使用 Spring MVC,对吗?

        【讨论】:

        • 我删除了customLogoutHandler()customLogoutSuccessHandler() 并尝试了您的解决方案,但没有看到任何效果。仍然当会话超时时,spring 将我重定向到登录 url。
        猜你喜欢
        • 2017-03-08
        • 1970-01-01
        • 1970-01-01
        • 2013-02-02
        • 1970-01-01
        • 2016-11-06
        • 2015-12-16
        • 2015-02-05
        • 2012-06-08
        相关资源
        最近更新 更多