如何设置弹簧安全会话超时?

Posted

技术标签:

【中文标题】如何设置弹簧安全会话超时?【英文标题】:How to set spring security session timeout? 【发布时间】:2020-03-29 02:31:30 【问题描述】:

我在 tomcat 服务器中使用 spring security。如何更改默认会话超时?

我尝试使用以下命令修改 web.xml:

<session-config>
         <session-timeout>1</session-timeout>
</session-config>

这似乎不起作用。

我也看到spring boot使用参数server.servlet.session.timeout,但是我没有使用spring boot。

【问题讨论】:

***.com/a/54195305/6622913 正如我的问题中所说,这是我尝试过的。但这似乎不起作用。更具体地说,我仍然在日志中看到 firing Filter: 'SecurityContextPersistenceFilter' 然后 Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT,即使 1 分钟已过期。 超时为 1 分钟。 Tomcat 有一个收割线程来终止超时会话,但是它大约每分钟运行一次。因此,实际上清理会话可能需要一分钟以上的时间。 我等了远远超过一分钟(比如 10 分钟),什么也没发生……你确定我写的配置应该强制用户在 1 分钟后重新验证吗?跨度> 【参考方案1】:

spring security中配置会话超时时间(maxInactiveInterval)的不同方式。

    通过在 web.xml 中添加会话配置

    通过创建 HttpSessionListener 的实现并将其添加到 servlet 上下文中。(来自 munilvc 的回答)

    通过在 spring 安全配置中注册您的自定义 AuthenticationSuccessHandler,并设置会话最大不活动间隔 在 onAuthenticationSuccess 方法中。

这种实现有优势

登录成功后,可以为不同的角色/用户设置不同的maxInactiveInterval值。

登录成功后,您可以在会话中设置用户对象,因此可以从会话中的任何控制器中访问用户对象。

缺点:您不能为匿名用户(未经身份验证的用户)设置会话超时

创建 AuthenticationSuccessHandler 处理程序

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler

public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
        throws IOException 

    Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
    if (roles.contains("ROLE_ADMIN"))
    
        request.getSession(false).setMaxInactiveInterval(60);
    
    else
    
        request.getSession(false).setMaxInactiveInterval(120);
    
    //Your login success url goes here, currently login success url="/"
    response.sendRedirect(request.getContextPath());


注册成功处理程序

Java 配置方式

@Override
protected void configure(final HttpSecurity http) throws Exception

    http
        .authorizeRequests()
            .antMatchers("/resources/**", "/login"").permitAll()
            .antMatchers("/app/admin/*").hasRole("ADMIN")
            .antMatchers("/app/user/*", "/").hasAnyRole("ADMIN", "USER")
        .and().exceptionHandling().accessDeniedPage("/403")
        .and().formLogin()
            .loginPage("/login").usernameParameter("userName")
            .passwordParameter("password")
            .successHandler(new MyAuthenticationSuccessHandler())
            .failureUrl("/login?error=true")
        .and().logout()
            .logoutSuccessHandler(new CustomLogoutSuccessHandler())
            .invalidateHttpSession(true)
        .and().csrf().disable();

    http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true");

xml配置方式

<http auto-config="true" use-expressions="true" create-session="ifRequired">
    <csrf disabled="true"/>

    <intercept-url pattern="/resources/**" access="permitAll" />
    <intercept-url pattern="/login" access="permitAll" />

    <intercept-url pattern="/app/admin/*" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/" access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN')" />
    <intercept-url pattern="/app/user/*" access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN')" />

    <access-denied-handler error-page="/403" />

    <form-login 
        login-page="/login"
        authentication-success-handler-ref="authenticationSuccessHandler"
        authentication-failure-url="/login?error=true" 
        username-parameter="userName"
        password-parameter="password" />

    <logout invalidate-session="false" success-handler-ref="customLogoutSuccessHandler"/>

    <session-management invalid-session-url="/login?expired=true">
        <concurrency-control max-sessions="1" />
    </session-management>
 </http>

 <beans:bean id="authenticationSuccessHandler" class="com.pvn.mvctiles.configuration.MyAuthenticationSuccessHandler" />

【讨论】:

感谢您的回答。我不确定我是否理解它。我希望这可以在 xml 配置文件中完成,而无需添加代码。这不可能吗? 可以像你说的那样做,但是你在“application.properties”文件中改变了什么吗?你有一个“server.servlet.session.timeout”值。附言此值以秒为单位。你也没有提到你想要什么,如果你想停用超时,你可以将它设置为零。【参考方案2】:

请记住,此值以秒为单位

<session-config>
         <session-timeout>1</session-timeout>
</session-config>

这个值会被四舍五入到分钟。

如果服务器没有收到来自例如你的 GUI 的任何请求,它将等待至少 1 分钟然后过期会话。

【讨论】:

以上是关于如何设置弹簧安全会话超时?的主要内容,如果未能解决你的问题,请参考以下文章

使会话弹簧安全性无效

如何使用 Spring 安全性获取会话超时消息

春季/安全中的自定义会话超时

如何在 Java Web 应用程序中动态设置会话超时?

春季安全会话超时

如何使用 Spring Boot 嵌入式 tomcat 设置会话超时