java - 我的不同 session 使用相同的最后一个 Activity 和 session ID 进行重复,为什么?

标签 java spring spring-security

我正在使用Spring Security,当我使用同一用户从不同的浏览器登录时(我设置为可以有多个 session ),从 Controller 传递的数据(我从每个主体获取SessionInformation) View 的内容被复制,而不是创建新的 session ID,并且最后一个 Activity 对于所有不同的浏览器 session 也是完全相同的。

这是 spring-security.xml 的一部分,其中配置了 sessionRegistry 等内容。

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

然后我将“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)。当我从一个浏览器发出一些请求时,最后一个 Activity 会同时在所有 session 中刷新。

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

最佳答案

这不是 session 的问题,而是 for 循环的问题。

每个用户仅创建一个 LoginUserInfos,并且该对象会在每个 session 中重复使用。因此,您只能看到最后一个 session 的数据。而是在内部循环中创建 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);
        }           
    }

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

关于java - 我的不同 session 使用相同的最后一个 Activity 和 session ID 进行重复,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15888862/

相关文章:

Java 异常处理 - Do while 循环

java - JUnit 5 缓存管理器初始化数据测试 - 空缓存管理器

java - 如何通过 jquery Easyui Combogrid 中的所有列添加搜索功能

java - 使用配置设置连接超时

java - spring security oauth2 (2.0.8) 使用 InMemory tokenstore 获取无效的访问 token

java - 使用 spring hibernate 上传和下载文件,对这种方法有点困惑。有人可以指导我吗......?

java - 如何使用具有字符输入和 boolean 输出的方法?

java - Netflix 假装异常

Spring:@ConfigurationProperties中的@NestedConfigurationProperty列表

xml - spring security 4 csrf 通过 xml 禁用