2

我正在使用spring security,当我使用同一用户(我设置为可能有多个会话)从不同的浏览器登录时,数据从控制器(我从每个主体获取SessionInformation)传递到视图正在复制而不是创建新的 Session Id,并且 Last Activity 对于所有不同的浏览器会话也是相同的。

这是配置 sessionRegistry 的 spring-security.xml 的一部分。

        <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 的控制器:

@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";
    }

然后我将“userSessionData”发送到这样的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 会同时在所有会话中刷新。

另一件事,当我从不同的浏览器注销时,会话应该终止。但是当我检查会话列表时,它仍然存在。为什么也会出现这种情况???

4

1 回答 1

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

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

于 2013-04-09T14:29:21.503 回答