Announcement Announcement Module
Collapse
No announcement yet.
Problem with Autowiring access to SessionRegistry in Concurrent Session configuration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with Autowiring access to SessionRegistry in Concurrent Session configuration

    I am pretty new to Spring and Spring Security. I have managed to secure my application in the way I wanted it (2 authentication methods and concurrency control). Spring Security is actually working.

    My problem is: I can not figure out, how to access the SessionRegistry used in the concurrent session management of Spring inside my own code. According to the documentation, a simple @Autowired instance declaration should be enough, but I must be missing something:

    Java Servlet code, where I want to access the sessionRegistry. But this object is always null, even if concurreny session management is working (I can debug this and also the logging shows, that the SessionRegistry object is created):

    Code:
    public class UserSelfService extends HttpServlet {
    	private static Log log = LogFactory.getLog(UserSelfService.class); 
    	private static final long serialVersionUID = 1L;
           
            @Autowired
    	SessionRegistry sessionRegistry;
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    		PrintWriter writer = response.getWriter();
    		writer.println("Autowired sessionRegistry: " + sessionRegistry);
    
                    [...]
    The security.xml file with the beans definitions. The part for concurrency control more to the end of the long file. It contains also the line "<context:annotation-config/>", which is the important part to activate the Spring autowire functionality.

    Code:
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	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.0.xsd
    		http://www.springframework.org/schema/context
    		http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    	<context:annotation-config/>
    	<context:property-placeholder location="WEB-INF/config.properties" />
    	
    	<!--  This is the spring security configuration. All other declarations are only used to create the references here. -->
    	<http auto-config="false" use-expressions="true" entry-point-ref="tenantAuthenticationEntryPoint">
    		<intercept-url pattern="/login.*" access="permitAll"/>
    		<intercept-url pattern="/sessioninfo.jsp" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
         	        <intercept-url pattern="/*" access="permitAll"/> 
        	        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
        	        <session-management session-authentication-strategy-ref="sas"/>
      		<custom-filter position="FORM_LOGIN_FILTER" ref="usernamePasswordAuthenticationFilter" />
      		<!-- The JanRain authentication filter reuses the filter position of the OpenID filter. -->
      		<custom-filter position="OPENID_FILTER" ref="janrainAuthenticationFilter" />
                    <logout logout-success-url="/login.html" />
    	</http>
    	
    	<!--  defines the login page to be used to authenticate a user, when a request is not authorized to access a Web resource -->
    	<beans:bean id="tenantAuthenticationEntryPoint"
    		class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    		<beans:property name="LoginFormUrl" value="/login.html"/>
    	</beans:bean>
    	
    	<beans:bean id="authenticationFailureHandler" class="com.tsystems.wlidp.security.WlidpAuthenticationFailureHandler">
    		<beans:property name="errorPage" value="/errorpage.jsp"/>
    	</beans:bean> 
    	
    	<!-- The authentication filter declarations -->
    	
    	<!-- the UsernamePasswordAuthenticationFilter needs special authenticationDetailsSource to grap the tenantId from the Http request -->
    	<beans:bean id="usernamePasswordAuthenticationFilter" class=
    		"org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    		<beans:property name="sessionAuthenticationStrategy" ref="sas" />
    		<beans:property name="authenticationManager" ref="authenticationManager"/>
    		<beans:property name="authenticationDetailsSource" ref="webAuthenticationDetailsSource"/>
     		<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>  
    	</beans:bean>
    
    	<!-- The JanRain authentication filter is a new class of the WL-IdP project. -->
    	<beans:bean id="janrainAuthenticationFilter" class=
    		"com.tsystems.wlidp.security.janrain.JanrainAuthenticationFilter">
    		<beans:property name="sessionAuthenticationStrategy" ref="sas" />
    		<beans:property name="authenticationManager" ref="authenticationManager"/>
    		<beans:property name="filterProcessesUrl" value="/j_spring_janrain_security_check"/>
    		<beans:property name="authenticationDetailsSource" ref="webAuthenticationDetailsSource"/>
    		<beans:property name="janrainService" ref="janrainService"/>
    		<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>
    	</beans:bean>	
    
    	<beans:bean class="org.springframework.security.web.authentication.WebAuthenticationDetailsSource" id="webAuthenticationDetailsSource">
    		<beans:property name="clazz" value="com.tsystems.wlidp.security.WlidpAuthenticationDetails"/>	
    	</beans:bean>
    	
    	<!-- The Spring authentication manager has to authentication methods: username-password and JanRain 3rd party -->
    	
    	<authentication-manager alias="authenticationManager">
    		<authentication-provider ref="tenantAuthProvider"/>		
    		<authentication-provider ref="janrainAuthenticationProvider"/>
    	</authentication-manager>
    
    	<beans:bean class="com.tsystems.wlidp.security.TenantAuthenticationProvider" id="tenantAuthProvider">
    		<beans:constructor-arg ref="tenantAuthenticator"/>
    		<beans:constructor-arg ref="tenantAuthoritiesPopulator"/>
    		<beans:property name="userDetailsContextMapper" ref="userContextMapper"/>
    	</beans:bean>
    
    	<beans:bean class="com.tsystems.wlidp.security.janrain.JanrainAuthenticationProvider" id="janrainAuthenticationProvider">
    		<beans:constructor-arg ref="tenantAuthoritiesPopulator"/>
    		<beans:constructor-arg name="janrainService" ref="janrainService"/>		
    		<beans:constructor-arg ref="userService"/>
    	</beans:bean>		
    
    	<!-- sub declarations used to create the two authentication providers -->
    	
    	......
    
    	<!--  Concurrent Session definitions -->
    	
    	<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:property name="exceptionIfMaximumExceeded" value="true"/>
    	</beans:bean>
    
    	<!-- <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />  -->
    	<beans:bean id="sessionRegistry" class="com.tsystems.wlidp.concurrent.TestSessionRegistryImpl"/>
    	 
    	<beans:bean id="concurrencyFilter"
       		class="org.springframework.security.web.session.ConcurrentSessionFilter">
      		<beans:property name="sessionRegistry" ref="sessionRegistry" />
      		<beans:property name="expiredUrl" value="/expired.html" />
    	</beans:bean>
    
    	<!--  The database layer declarations -->
    	
    	....
    	 	
    </beans:beans>
    I even tried to use my own TestSessionRegistryImpl class, to have a way to access the sessionRegistry programmatically via a singleton class instance being set. Via this singleton, I have access to the sessionRegistry, but this is not a good way. I really like to get the "@Autowired" feature to work.

    Code:
    public class TestSessionRegistryImpl extends SessionRegistryImpl {
    	public static TestSessionRegistryImpl singleton;
    	
    	public TestSessionRegistryImpl() {
    		super();
    		singleton = this;
    	}
    
    }
    Last edited by Chim; Nov 16th, 2010, 10:52 AM.

  • #2
    I suggest the reference guide.

    Spring only injects beans it can control, your servlet isn't controller by spring but by the servlet container. You will have to do a lookup instead of an injection.

    Comment


    • #3
      Thank you, that explains my failures.

      Is there an easy way for my Servlet to lookup an object created for Spring Security via the web.xml parameterization?

      <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/userselfservice-security.xml /WEB-INF/app-base.xml</param-value>
      </context-param>

      The Spring manual has always code examples, where I create new beans via reading an XML file. But the bean I am interested in has already been created and I do not want to create new objects, but access the "Singleton" SessionRegistryImpl from Spring Security's concurreny session management control.

      PS: At the moment I use a workaround, where I store the SessionRegistryImpl created by Spring Security as a static attribute to a certain class and can access it from there.

      Comment


      • #4
        I think I figured it out at least. It seems to be as simple as this static method:

        WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();

        I haven't used Spring MVC, but as Spring Security is working on the Web layer, this is obviously the place to look at.

        I hope this is the right approach...

        Comment


        • #5
          Well the better approach (imho) is to use WebApplicationContextUtils to get access. But as stated IMHO that is ofcourse .

          Comment


          • #6
            Thanks again Marten!

            Comment

            Working...
            X