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