Announcement Announcement Module
Collapse
No announcement yet.
SecurityContextHolder.getContext().getAuthenticati on() returns null Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SecurityContextHolder.getContext().getAuthenticati on() returns null

    I have a 'standard' web app configuration and have successfully logged on and retrieved the Authentication object in JSP like so:

    Code:
    <c:out value="${securityContext == null}" /> <br/> 
    <c:out value="${securityContext}" /> <br/>
    <c:out value="${authentication}" /> <br/>
    <c:out value="${isAuthenticated}" /> <br/>
    <c:out value="${user}" /> <br/>
    Gives:

    Code:
    false
    org.acegisecurity.context.SecurityContextImpl@440a0253: Authentication: [email protected]40a0253: Username: timeout.persistence.entity.Person@1; Password: [PROTECTED]; Authenticated: true; Details: org.acegisecurity.ui.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: C970FECAD279BBAFCDFCD860E3DCE62F; Granted Authorities: ROLE_USER
    [email protected]40a0253: Username: timeout.persistence.entity.Person@1; Password: [PROTECTED]; Authenticated: true; Details: org.acegisecurity.ui.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: C970FECAD279BBAFCDFCD860E3DCE62F; Granted Authorities: ROLE_USER
    true
    timeout.persistence.entity.Person@1
    and seen the same when I list the session contents in an Action

    But the Tags don't work, ie
    <authz:authentication operation="username" />
    outputs nothing (yes taglib declared)

    and perhaps most telling is if I do:

    SecurityContextHolder.getContext().getAuthenticati on()
    it evaluates to null.

    Here's the Spring, but it is pretty much identical to the petclinic app.
    Some posts with possibly the same problem mention filter order, but I've tried all sorts, to no avail. Please help me!

    Code:
    <beans>
    
    	<bean id="filterChainProxy"
    		class="org.acegisecurity.util.FilterChainProxy">
    		<property name="filterInvocationDefinitionSource">
    			<value>
    				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    				PATTERN_TYPE_APACHE_ANT
    				/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
    			</value>
    		</property>
    	</bean>
    
    	<bean id="httpSessionContextIntegrationFilter" 
    		class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />  
    	
    	<bean id="logoutFilter"
    		class="org.acegisecurity.ui.logout.LogoutFilter">
    		<constructor-arg value="/index.do" />
    		<!-- URL redirected to after logout -->
    		<constructor-arg>
    			<list>
    				<ref bean="rememberMeServices" />
    				<bean
    					class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
    			</list>
    		</constructor-arg>
    	</bean>
    
    	<!-- This is the one for form based authentication -->
    	<bean id="authenticationProcessingFilter"
    		class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
    		<property name="authenticationManager" ref="authenticationManager" />
    		<property name="authenticationFailureUrl" value="/login.do" />
    		<property name="defaultTargetUrl" value="/index.do" />
    		<property name="filterProcessesUrl" value="/j_acegi_security_check" />
    		<property name="rememberMeServices" ref="rememberMeServices" />
    	</bean>
    
    	<bean id="securityContextHolderAwareRequestFilter"
    		class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />
    
    	<bean id="rememberMeProcessingFilter"
    		class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
    		<property name="authenticationManager" ref="authenticationManager" />
    		<property name="rememberMeServices" ref="rememberMeServices" />
    	</bean>
    
    	<bean id="anonymousProcessingFilter"
    		class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
    		<property name="key" value="changeThis" />
    		<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS" />
    	</bean>
    
    	<bean id="exceptionTranslationFilter"
    		class="org.acegisecurity.ui.ExceptionTranslationFilter">
    		<property name="authenticationEntryPoint">
    			<bean
    				class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
    				<property name="loginFormUrl" value="/login.do" />
    				<property name="forceHttps" value="false" />
    			</bean>
    		</property>
    		<property name="accessDeniedHandler">
    			<bean
    				class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
    				<property name="errorPage" value="/login.jsp" />
    			</bean>
    		</property>
    	</bean>
    
    	<bean id="filterInvocationInterceptor"
    		class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
    		<property name="authenticationManager" ref="authenticationManager" />
    		<property name="accessDecisionManager">
    			<bean class="org.acegisecurity.vote.AffirmativeBased">
    				<property name="allowIfAllAbstainDecisions"
    					value="false" />
    				<property name="decisionVoters">
    					<list>
    						<bean class="org.acegisecurity.vote.RoleVoter" />
    						<bean class="org.acegisecurity.vote.AuthenticatedVoter" />
    					</list>
    				</property>
    			</bean>
    		</property>
    		<property name="objectDefinitionSource">
    			<value>
    				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    				PATTERN_TYPE_APACHE_ANT
    				/login.jsp=IS_AUTHENTICATED_ANONYMOUSLY
    				/**=IS_AUTHENTICATED_REMEMBERED
    			</value>
    		</property>
    	</bean>
    
    	<bean id="rememberMeServices"
    		class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
    		<property name="userDetailsService" ref="userDetailsService" />
    		<property name="key" value="changeThis" />
    	</bean>
    
    	<bean id="authenticationManager"
    		class="org.acegisecurity.providers.ProviderManager">
    		<property name="providers">
    			<list>
    				<ref local="daoAuthenticationProvider" />
    				<bean
    					class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
    					<property name="key" value="changeThis" />
    				</bean>
    				<bean
    					class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
    					<property name="key" value="changeThis" />
    				</bean>
    			</list>
    		</property>
    	</bean>
    
    	<bean id="daoAuthenticationProvider"
    		class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
    		<property name="userDetailsService" ref="userDetailsService" />
    		<property name="userCache">
    			<bean
    				class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
    				<property name="cache">
    					<bean
    						class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    						<property name="cacheManager">
    							<bean
    								class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
    						</property>
    						<property name="cacheName" value="userCache" />
    					</bean>
    				</property>
    			</bean>
    		</property>
    	</bean>
    
    	<!-- UserDetailsService is the most common Acegi Security interface implemented by end users -->
    	<bean id="userDetailsService" 
    			class="timeout.security.TimeoutUserDetailsService" >			
    		<property name="personDao" ref="personDao" />	
    	</bean>
    
    
    	<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
    	<bean id="loggerListener"
    		class="org.acegisecurity.event.authentication.LoggerListener" />
    
    </beans>
    Last edited by visionset; Dec 2nd, 2006, 05:45 PM.

  • #2
    Just having a quick scan over it, it looks word perfect in comparison to the shipped Acegi example. There are a few differences. The UserDetailsService, which makes sense and some of the forwards.

    authenticationEntryPoint has the loginFormUrl as a Struts style action, where does this come from isn't it just /login.jsp?
    <property name="loginFormUrl" value="/login.do" />

    authenticationProcessingFilter has the authenticationFailureUrl as a Struts style action, as above.
    <property name="authenticationFailureUrl" value="/login.do" />

    I'm not sure these differences would cause problems however. Can we have a look at your web.xml and the UserDetailsService?
    Last edited by karldmoore; Dec 2nd, 2006, 11:24 AM.

    Comment


    • #3
      Just to be quite clear.
      The Acegi authentication mechanism appears to work correctly and there is logging output after a call to /j_acegi_security_check.
      However any attempt to add code tags or plain java code calls (JSP or Action), retrieves a null Authentication object and no Authz tags work. ie no username can be output and the authorisation tag does not reveal content that the logging mentioned above clearly suggests the current user is in ROLE for.

      Thanks for any help anyone can give.

      Comment


      • #4
        web.xml and UserDetails as requested

        Originally posted by karldmoore View Post
        Just having a quick scan over it, it looks word perfect in comparison to the shipped Acegi example. The only difference is the UserDetailsService, which makes sense. Can we have a look at your web.xml and the UserDetailsService?
        You surely can, here you go...

        WEB.xml:

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        
        <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
        	version="2.4">
        
        	<display-name>My WebWork Application</display-name>
        
        	<!-- Webwork config -->
        	<filter>
        		<filter-name>webwork</filter-name>
        		<filter-class>
        			com.opensymphony.webwork.dispatcher.FilterDispatcher
        		</filter-class>
        	</filter>
        
        	<filter-mapping>
        		<filter-name>webwork</filter-name>
        		<url-pattern>/*</url-pattern>
        	</filter-mapping>
        
        	<listener>
        		<listener-class>
        			org.springframework.web.context.ContextLoaderListener
        		</listener-class>
        	</listener>
        
        	<!-- Context Configuration locations for Spring XML files -->
        	<context-param>
        		<param-name>contextConfigLocation</param-name>
        		<param-value>
        			/WEB-INF/classes/applicationContext/*.xml
        		</param-value>
        	</context-param>
        	
        	<!--  Acegi config -->
        	<filter>
        		<filter-name>Acegi Filter Chain Proxy</filter-name>
        		<filter-class>
        			org.acegisecurity.util.FilterToBeanProxy
        		</filter-class>
        		<init-param>
        			<param-name>targetClass</param-name>
        			<param-value>
        				org.acegisecurity.util.FilterChainProxy
        			</param-value>
        		</init-param>
        	</filter>
        
        	<filter-mapping>
        		<filter-name>Acegi Filter Chain Proxy</filter-name>
        		<url-pattern>/*</url-pattern>
        	</filter-mapping>
        	
        	<!-- Test servlet framework bypass of webwork -->
        	<servlet>
        		<servlet-name>HelloWorld</servlet-name>
        		<servlet-class>
        			timeout.helloworld.HelloWorldServlet
        		</servlet-class>
        		<load-on-startup>1</load-on-startup>
        	</servlet>
        
        	<servlet-mapping>
        		<servlet-name>HelloWorld</servlet-name>
        		<url-pattern>/test_servlet</url-pattern>
        	</servlet-mapping>
        
        
        </web-app>
        UserDetailsService :
        Code:
        package timeout.security;
        
        import org.acegisecurity.userdetails.UserDetails;
        import org.acegisecurity.userdetails.UserDetailsService;
        import org.acegisecurity.userdetails.UsernameNotFoundException;
        import org.hibernate.HibernateException;
        import org.springframework.dao.DataAccessException;
        import org.springframework.orm.hibernate3.HibernateSystemException;
        
        import timeout.persistence.dao.PersonDao;
        import timeout.persistence.entity.Person;
        
        public class TimeoutUserDetailsService implements UserDetailsService {
        
        	private PersonDao personDao;
        	
        	public UserDetails loadUserByUsername(String username) 
        			throws UsernameNotFoundException, DataAccessException {
        		
        		Person person;
        		
        		try {
        			person = personDao.locateByUserName(username);
        		}
        		catch (Throwable t) {
        			if (t instanceof HibernateException) throw new 
        				HibernateSystemException((HibernateException)t);
        			else throw new RuntimeException(
        				"Problem running query to locate '" + username + "'", t);
        		}
        		
        		if (person == null) throw new UsernameNotFoundException(
        			"no user found for '" + username + "'");
        		
        		return person;
        	}
        
        	public void setPersonDao(PersonDao personDao) {
        		this.personDao = personDao;
        	}
        
        }

        Comment


        • #5
          Again that all looks fine. I the only thing I would say is that there are two filters that match /* in your configuration. Again I'm not really sure what that might do. I updated my earlier post with some other points, might want to check them out as well.

          When I used Acegi with Struts my mapping looked like this.

          Code:
              <servlet-mapping>
                  <servlet-name>action</servlet-name>
                  <url-pattern>*.do</url-pattern>
              </servlet-mapping>

          Comment


          • #6
            [QUOTE=karldmoore;88512]
            authenticationEntryPoint has the loginFormUrl as a Struts style action, where does this come from isn't it just /login.jsp?
            <property name="loginFormUrl" value="/login.do" />

            authenticationProcessingFilter has the authenticationFailureUrl as a Struts style action, as above.
            <property name="authenticationFailureUrl" value="/login.do" />

            [QUOTE/]

            Normally it would be /login.action with webwork but I changed the defautl extension. I guessed the value should be the URL to deliver the login form. I believe all requests should go through an action (as is the webwork way) and the action does little at the moment, just dispatches the JSP /login.jsp

            Besides, All my JSP's are under WEB-INF so I have to go through Actions.

            I have just tried it with a JSP outside WEB-INF and it WORKED

            But I DO want my jsps all under WEB-INF :-(

            Comment


            • #7
              OK, so its working then? In my apps all of the jsps are under WEB-INF/jsp, the only exception is a default page (welcome.jsp) that forwards on to login.

              Comment


              • #8
                Originally posted by karldmoore View Post
                OK, so its working then? In my apps all of the jsps are under WEB-INF/jsp, the only exception is a default page (welcome.jsp) that forwards on to login.
                Yes thanks very much for spotting the possible cause.
                Hey, I'm just down the road from you, in Nottingham!!

                I wonder why it doesn't work when you go through an Action, sure be nice if it did.

                Thanks again.

                Comment


                • #9
                  Still no workable solution

                  Actually, no, I don't have a workable solution.
                  In fact I've solved the issue so long as I stay outside of WEB-INF
                  I thought I'd cracked it by having the one page to forward to outside then it'd be okay, but no. As soon as I use a page inside WEB-INF the same problem. Null Authentication object and broken Authz tags.

                  The filter thing you mentioned with both filters having /* pattern. Should not be a problem since it just means both filters will run for all requests. As they should.

                  I can't believe no one's come across this problem before. I mean Acegi + Webwork is a common enough combination. WW recommend Acegi!

                  Comment


                  • #10
                    Hey, I'm just down the road from you, in Nottingham!!
                    I actually work in Nottingham, near Hucknall.

                    In fact I've solved the issue so long as I stay outside of WEB-INF
                    I've got a demo that uses Struts with the approach I descibed earlier, mail me if you want me to send it, might help.

                    The filter thing you mentioned with both filters having /* pattern. Should not be a problem since it just means both filters will run for all requests. As they should.
                    I appreciate that, its just there are lots issues regarding filter order on this forum. I remember one about Sitemesh being problematic and thought this might be a similar thing.

                    Comment

                    Working...
                    X