I am using Spring Security and I would like to know which users are online now. At first I tried the approach using SessionRegistryImpl and <session-management session-authentication-strategy-ref="..." ... /> , but I think this list is stored in memory, and I would like to avoid it (it will be a huge website, and many users will be simultaneously online, the List can become huge). Please correct me if I am wrong.
The second approach I tried is to use the listener and the HttpSessionListener interface and the user AuthenticationManager and store the "online flag" in the database. Basically, the flag is set to true in the authenticate(...) method of my authentication manager and set to false in the sessionDestroyed(...) method of my session listener.
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Test</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/security.xml</param-value> </context-param> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>my.package.SessionListener</listener-class> </listener> <servlet> <servlet-name>test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <session-config> <session-timeout>1</session-timeout> </session-config> </web-app>
Spring Security Configuration:
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <beans:bean id="authenticationManager" class="my.package.security.AuthenticationManager" /> <http disable-url-rewriting="true" authentication-manager-ref="authenticationManager"> <intercept-url pattern="/login*" access="ROLE_ANONYMOUS" /> <intercept-url pattern="/favicon.ico" access="ROLE_ANONYMOUS" /> <intercept-url pattern="/*" access="ROLE_USER" /> <form-login login-processing-url="/authorize" login-page="/login" authentication-failure-url="/login-failed" /> <logout logout-url="/logout" logout-success-url="/login" /> <remember-me data-source-ref="dataSource" /> </http> </beans:beans>
my.package.SessionListener:
public class SessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent httpSessionEvent) { } public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { UserJpaDao userDao = WebApplicationContextUtils.getWebApplicationContext(httpSessionEvent.getSession().getServletContext()).getBean(UserJpaDao.class); Authentication a = SecurityContextHolder.getContext().getAuthentication(); if(a != null) { User loggedInUser = userDao.findByAlias(a.getName()); if(loggedInUser != null) { loggedInUser.setOnline(false); userDao.save(loggedInUser); } } } }
my.package.security.AuthenticationManager:
public class AuthenticationManager implements org.springframework.security.authentication.AuthenticationManager { @Autowired UserJpaDao userDao; public Authentication authenticate(Authentication authentication) throws AuthenticationException { User loggedInUser = null; Collection<? extends GrantedAuthority> grantedAuthorities = null; ... loggedInUser = userDao.findByAlias(authentication.getName()); if(loggedInUser != null) {
sessionCreated and sessionDestroyed start correctly, but SecurityContextHolder.getContext().getAuthentication(); always null.
Update: almost everything works fine. The only problem is that when the session expires due to a timeout, SecurityContextHolder.getContext().getAuthentication() returns null in the sessionDestroyed(...) method. It works great when logging out manually.
Can someone help me? Any hints are welcome.
thanks
spring spring-security session
satoshi
source share