问题 spring security - expiredUrl无效


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

@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 网址,然后重定向到他 /admin/login 网址。

更新:

我在评论和答案中尝试了建议的解决方案,但没有看到任何影响。我也删除了 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;
}

谁能帮我解决这个问题?


2315
2018-04-26 12:31


起源

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


答案:


我试过了 阿里德哈尼以这种方式解决方案(在评论中):

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

并作为 编码员 说,补充一下 "/expired" 在允许的网址中,问题解决了。谢谢所有关注我的问题的人,特别是 阿里德哈尼 和 编码员,他们有用的评论。


8
2018-05-02 04:22





ConcurrentSessionFilter 将重定向到 expiredUrl,如果 有效 会话ID标记为已过期 SessionRegistry,见 Spring Security参考

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

SessionManagementFilter 将重定向到 invalidSessionUrl,如果会话ID不是 有效 (超时或错误的ID),请参阅 Spring Security参考

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

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

顺便说一句:如果你想使用 并发会话控制 同 maximumSessions 你必须补充 HttpSessionEventPublisher 到你的 web.xml

并发会话控制

如果您希望对单个用户登录应用程序的能力施加约束,Spring Security会通过以下简单添加为开箱即用提供支持。首先,您需要将以下侦听器添加到您的 web.xml 文件以保持Spring Security有关会话生命周期事件的更新:

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

5
2018-05-01 18:56





理想情况下,您的UX应该只是将用户重定向回登录页面。我猜你看到有一个专用/过期页面的要求,因为 Spring MVC - 动态更改安全设置 在那里你了解了你需要有单独的登录掩码。如果解决方法(我在其他问题的答案中描述的那个)适合您,您可以放弃使用专用/过期页面的要求,并使用解决方案编号直接将用户重定向到正确的登录页面( 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,对吗?


0
2018-04-28 18:42



我删除了 customLogoutHandler() 和 customLogoutSuccessHandler() 并尝试了你的解决方案,但没有看到任何影响。当会话超时时,spring会将我重定向到登录URL。 - hamed


如果你使用 的UserDetails 和 的UserDetailsS​​ervice 那应该是因为你的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());
    }
}

0
2017-09-18 07:49