我的不同会话与最后一个活动和会话ID重复,为什么?

时间:2013-04-08 20:59:05

标签: java spring spring-security

我使用Spring安全性,当我使用相同的用户(我设置为可能有多个会话)从不同的浏览器登录时,从控制器传递的数据(我从中获取SessionInformation)对于视图正在被复制而不是创建新的会话ID,并且最后一个活动对于所有不同的浏览器会话也是如此。

这是spring-security.xml的一部分,其中配置了sessionRegistry和stuff。     
                                                                

        <form-login login-page="/login" default-target-url="/welcome" always-use-default-target="true"
            authentication-failure-url="/loginfailed"/>
        <logout logout-success-url="/logout" />

        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
        <custom-filter after="FORM_LOGIN_FILTER" ref="myAuthFilter" />   
        <session-management session-authentication-strategy-ref="sas"/>
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="ldapAuthProvider">
        </authentication-provider>
    </authentication-manager>

<beans:bean id="concurrencyFilter"
       class="org.springframework.security.web.session.ConcurrentSessionFilter">
      <beans:property name="sessionRegistry" ref="sessionRegistry" />
    </beans:bean>

    <beans:bean id="myAuthFilter" class=
       "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
      <beans:property name="sessionAuthenticationStrategy" ref="sas" />
      <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>

    <beans:bean id="sas" class=
     "org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
      <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
      <beans:property name="maximumSessions" value="-1" />
    </beans:bean>

    <beans:bean id="sessionRegistry" 
        class="org.springframework.security.core.session.SessionRegistryImpl" />

这是使用sessionRegistry的Controller:

@RequestMapping(value = "/activeusers", method = RequestMethod.GET)
    public String manageActiveUsers(ModelMap model, Principal principal) {
        String name = principal.getName();
        model.addAttribute("username", name);
        List<LoginUserInfo> userSessionData = new ArrayList<LoginUserInfo>();       

        List<Object> principals = sessionRegistry.getAllPrincipals();

        //TODO: Find a better way to get the remote IP Address according to each client call
        String remoteAddress = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
           .getRequest().getLocalAddr();

        for (Object object : principals) {
            LoginUserInfo userInfo = new LoginUserInfo();
            LdapUserDetailsImpl user = (LdapUserDetailsImpl) object;
            List<SessionInformation> sessions = sessionRegistry.getAllSessions(user, false);
            String username = user.getUsername();

            for (SessionInformation session : sessions) {
                Date lastRequest = session.getLastRequest();
                String sessionId = session.getSessionId();

                userInfo.setUsername(username);
                userInfo.setIp(remoteAddress);
                userInfo.setLastActivity(lastRequest.getTime());
                userInfo.setSessionId(sessionId);

                userSessionData.add(userInfo);
            }           
        }

        model.addAttribute("userSessionData", userSessionData);

        return "activeusers";
    }

然后我发送&#34; userSessionData&#34;像这样的jsp VIEW。

                  <c:forEach var="userDetail" items="${userSessionData}">
                      <tr>
                        <td><c:out value="${userDetail.ip}"/></td>
                        <td><c:out value="${userDetail.username}"/></td>
                        <td><c:out value="${userDetail.lastActivity}"/></td>
                        <td><c:out value="${userDetail.sessionId}"/></td>
                      </tr>
                   </c:forEach>

正如我所说,即使我从另一个浏览器登录,所有与用户相关的数据都被复制(sessionId和lastActivity)。当我从一个浏览器做一些请求时,lastActivity会同时在所有会话中刷新。

另一件事,当我从不同的浏览器注销时,会话终止。但是当我检查会话列表时,仍然存在。为什么会这样呢???

1 个答案:

答案 0 :(得分:2)

这不是您的会话的问题,这是您的for循环的问题。

每个用户只能创建一个LoginUserInfos,并且会为每个会话重复使用此对象。因此,您只能看到上次会话的数据。而是在内部循环中创建LoginUserInfos

    for (Object object : principals) {
        LdapUserDetailsImpl user = (LdapUserDetailsImpl) object;
        List<SessionInformation> sessions = sessionRegistry.getAllSessions(user, false);
        String username = user.getUsername();

        for (SessionInformation session : sessions) {
            LoginUserInfo userInfo = new LoginUserInfo();
            Date lastRequest = session.getLastRequest();
            String sessionId = session.getSessionId();

            userInfo.setUsername(username);
            userInfo.setIp(remoteAddress);
            userInfo.setLastActivity(lastRequest.getTime());
            userInfo.setSessionId(sessionId);

            userSessionData.add(userInfo);
        }           
    }

这应该会给你预期的结果。