Java Spring安全性:SecurityContextHolder未填充匿名令牌,因为它已包含

Java Spring安全性:SecurityContextHolder未填充匿名令牌,因为它已包含,java,spring,spring-mvc,spring-security,session-state,Java,Spring,Spring Mvc,Spring Security,Session State,我正在开发一个SpringMVC应用程序,它使用SpringSecurity进行身份验证和相关的安全目的。目前,我在查询sessionRegistry以获取当前联机用户列表时遇到问题,因为GetAllPrinciples方法始终包含NULL。我尝试了文档中提到的解决方案以及其他SO线程中提到的许多建议。我会非常感谢一些帮助,因为我正在尝试各种组合,这将工作,以获得所有在线用户的名单 以下是我的security-application-context.xml: <import re

我正在开发一个SpringMVC应用程序,它使用SpringSecurity进行身份验证和相关的安全目的。目前,我在查询sessionRegistry以获取当前联机用户列表时遇到问题,因为GetAllPrinciples方法始终包含NULL。我尝试了文档中提到的解决方案以及其他SO线程中提到的许多建议。我会非常感谢一些帮助,因为我正在尝试各种组合,这将工作,以获得所有在线用户的名单

以下是我的security-application-context.xml:

     <import resource="servlet-context.xml" />

    <!-- Global Security settings -->
    <security:global-method-security pre-post-annotations="enabled" />
    <security:http pattern="/resources/**" security="none"/>

    <security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
        <security:form-login login-page="/login" login-processing-url="/j_spring_security_check" default-target-url="/canvas/list" always-use-default-target="false" authentication-failure-url="/denied.jsp" />
        <security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService" token-validity-seconds="1209600" data-source-ref="dataSource"/>
        <security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
    <security:port-mappings>
        <security:port-mapping http="80" https="443"/>
    </security:port-mappings>
    <security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
    </security:http>
        <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
        <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="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:property name="key" value="_spring_security_remember_me" />
        <property name="alwaysRemember" value="true"/>
        <beans:property name="tokenRepository" ref="jdbcTokenRepository"/>
        <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
    </beans:bean>
 <beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="sessionAuthenticationStrategy" ref="sas"/>
        <property name="rememberMeServices" ref="rememberMeAuthenticationProvider"/>
        <property name="allowSessionCreation" value="true"/>
        <property name="authenticationManager" ref="authenticationManager"/>
    </beans:bean>
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider user-service-ref="LoginServiceImpl">
           <security:password-encoder  ref="encoder"/>
        </security:authentication-provider>
    </security:authentication-manager>
    <beans:bean id="encoder"             class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="11" />
    </beans:bean>
    <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
               <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>
以下是我试图获取在线用户列表的地方:

@Service
@Transactional
public class OnlineUsersServiceImpl implements OnlineUsersService {

  @Autowired
    @Qualifier("sessionRegistry")
    private SessionRegistry sessionRegistry;

 @Override
    public boolean checkIfUserhasSession(int id) {

        Person person = this.personService.getPersonById(id);
        String email = person.getUsername();
        List<Object> principals = sessionRegistry.getAllPrincipals();
        for (Object principal : principals) {
            // It never reaches here
            System.out.println("We reached here");
            if (principal instanceof User) {
                  String username = ((User) principal).getUsername();
                System.out.println("Username is "+username);
                    if(email.equals(username)){
                        return true;
                    }

            }
        }
        return false;
    }

任何帮助都很好。自从3-4天以来,我一直在做这件毫无希望的事情。

在注入会话注册表之前,您需要在security-application-context.xml中定义会话管理部分

在并发控制部分,您应该为会话注册表对象设置别名

<security:http access-denied-page="/error403.jsp" use-expressions="true" auto-config="false">
        <security:session-management session-fixation-protection="migrateSession" session-authentication-error-url="/login.jsp?authFailed=true"> 
            <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.html" session-registry-alias="sessionRegistry"/>
        </security:session-management>

    ...
    </security:http>
用于基于java的配置替代xml配置


您需要在web.xml-listener中对登录/注销事件进行其他配置

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

如果我默认使用5个会话,可以吗?因为我们希望在多个设备上有多个会话。另外,我没有您上面提到的文件,我认为它不会影响任何其他功能。顺便说一句,您从Spring Boot给了我ServletListenerRegistrationBean,我没有使用Spring Boot。我正在使用SpringMVC。我收到错误ServletListenerRegistrationBean,无法解析符号。正因为如此,受保护的void configure方法没有从其超类中删除方法。Pastebin链接:Java部分和xml是相互替代的,我已经编辑了文件名。尝试了你的新代码,抱歉,它没有改变任何东西。你想让我放一些其他的文件让你知道发生了什么吗?
<listener>
   <listener-class>
    org.springframework.security.web.session.HttpSessionEventPublisher
   </listener-class>
</listener>