Announcement Announcement Module
Collapse
No announcement yet.
Custom UserDetailsService with autowired beans doesn't work Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Custom UserDetailsService with autowired beans doesn't work

    Hi,
    I am trying to add spring security 3.0.5 to a GWT 2.1.1 application but something seems to elude me. I have a custom UserDetailsService with autowired beans. I'm using a hibernate 3.5.0 datasource. When I run the app i get the login page but when hit submit, im not logged in and there is no error or exceptions spewed by my code. When I use println statements to look how far the request goes in trying to log me in? it gets stuck at the findByUsername method on my UserDaoImpl class. Could someone show me where I'm going wrong.


    Code:
    import java.util.List;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    import org.springframework.stereotype.Repository;
    import com.kibyegn.client.model.User;
    
    @Repository("userDao")
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    	
    	public void saveUser(User entity) {
    		getHibernateTemplate().saveOrUpdate(entity);
    	}
    
    
    	@SuppressWarnings("unchecked")
    	public User findByUsername(String username) {
    		List<User> temp = getHibernateTemplate().find("select h from users h where username='" + username + "'");
    		if (temp.size() > 0) {
    			System.out.println("Temp is not null");
    			return temp.get(0);
    		} else {
    			System.out.println("Temp is null");
    			return null;
    		}
    	}
    }
    This class extends UserDao which has 2 methods findByUsername() and saveUser().

    Code:
    import com.kibyegn.client.dao.UserDao;
    import com.kibyegn.client.model.User;
    
    @Service("userDetailsService")
    public class UserDetailsServiceImpl implements UserDetailsService {
    
    	@Autowired private UserDao dao;
    
    	@Transactional(readOnly = true)
    	public UserDetails loadUserByUsername(String username)
    			throws UsernameNotFoundException, DataAccessException {
    		User userEntity = dao.findByUsername(username);
    		if (userEntity == null) {
    			throw new UsernameNotFoundException("user not found");
    		} else {
    			String name = userEntity.getUsername();
    			String password = userEntity.getPassword();
    			boolean enabled = userEntity.isEnabled();
    			boolean accountNonExpired = userEntity.isEnabled();
    			boolean credentialsNonExpired = userEntity.isEnabled();
    			boolean accountNonLocked = userEntity.isEnabled();
    
    			System.out.println(name + ", " + password + ", " + enabled + ", "
    					+ accountNonExpired + ", " + credentialsNonExpired + ", "
    					+ accountNonLocked);
    
    			Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    			authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
    
    			return new User(authorities, name, password, enabled,
    					accountNonExpired, credentialsNonExpired, accountNonLocked);
    		}
    	}
    }
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.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" default-autowire="byName">
                            
        <context:component-scan base-package="com.kibyegn.server.auth">
            <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Repository"/>
        </context:component-scan>
    
        <beans:import resource="applicationContext-dao.xml" />
    
        <http auto-config="true">
            <intercept-url pattern="/kibyegn/**" access="ROLE_USER"/>
            <intercept-url pattern="/gwt/**" access="ROLE_USER"/>
            <intercept-url pattern="/**/*.html" access="ROLE_USER"/>
            <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
            <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
            <form-login login-page="/login.jsp"/>
        </http>
    	
    	<beans:bean id="daoAuthenticationProvider"
     class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
      <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>
    
    <beans:bean id="authenticationManager"
        class="org.springframework.security.authentication.ProviderManager">
      <beans:property name="providers">
        <beans:list>
          <beans:ref local="daoAuthenticationProvider" />
        </beans:list>
      </beans:property>
    </beans:bean>
    
    <authentication-manager>
      <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="md5"/>
      </authentication-provider>
    </authentication-manager>
            
    </beans:beans>
    applicationContext.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    	<!-- DATASOURCE DEFINITON-->
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-autowire="byName">
    
        <context:component-scan base-package="com.kibyegn.client.dao">
            <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Repository"/>
        </context:component-scan>
    
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="org.postgresql.Driver" />
    		<property name="url" value="jdbc:postgresql://127.0.0.1:5432/GwtApp" />
    		<property name="username" value="postgres" />
    		<property name="password" value="password" />
    	</bean>
    	<!-- HIBERNATE CONFIGURATION -->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="annotatedClasses">
    			<list>
    				<value>com.kibyegn.client.model.User</value>
    			</list>
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
    				<prop key="hibernate.show_sql">true</prop>
    				<prop key="hibernate.hbm2ddl.auto">update</prop>
    			</props>
    		</property>
    	</bean>
    	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    		<property name="sessionFactory" ref="sessionFactory" />
    	</bean>
    	<bean id="userDao"
    		class="com.kibyegn.client.dao.UserDaoImpl"
    		scope="singleton">
    		<property name="hibernateTemplate" ref="hibernateTemplate" />
    	</bean>
    	
    	<bean id="userDetailsService"
    		class="com.kibyegn.server.auth.UserDetailsServiceImpl">
    	</bean>
    </beans>
    applicationContext-dao.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
      <!-- Spring security filters -->
      <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>
    			org.springframework.web.context.request.RequestContextListener</listener-class>
    	</listener>
    
    	<filter>
    		<filter-name>hibernateFilter</filter-name>
    		<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    	</filter>
    
    	<filter-mapping>
    		<filter-name>hibernateFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
      
      <!-- Servlets -->
      <servlet>
        <servlet-name>greetServlet</servlet-name>
        <servlet-class>com.kibyegn.server.GreetingServiceImpl</servlet-class>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>greetServlet</servlet-name>
        <url-pattern>/kibyegn/greet</url-pattern>
      </servlet-mapping>
      
      <servlet>
    	<servlet-name>authServlet</servlet-name>
    	<servlet-class>com.kibyegn.server.AuthServiceImpl</servlet-class>
      </servlet>
    
      <servlet-mapping>
    	<servlet-name>authServlet</servlet-name>
    	<url-pattern>/kibyegn/auth</url-pattern>
      </servlet-mapping>
      
      <!-- Default page to serve -->
      <welcome-file-list>
        <welcome-file>kibyegn.html</welcome-file>
      </welcome-file-list>
    
    </web-app>
    web.xml

  • #2
    Originally posted by kibyegon View Post
    it gets stuck at the findByUsername method on my UserDaoImpl class.
    Can you elaborate on this? I would also turn up logging for Spring Security to see what is happening.

    Comment


    • #3
      Originally posted by rwinch View Post
      Can you elaborate on this? I would also turn up logging for Spring Security to see what is happening.
      Thanks rwinch for taking your time to help. That was a good idea. Ive turned on logging and now I have some debug info that I can use. I think the problem lies in my mapping of the userDao. This is what the debug shows.

      Code:
      [DEBUG] [btpool0-0 11:15:40] (AbstractAuthenticationProcessingFilter.java:doFilter:193) Request is to process authentication
      [DEBUG] [btpool0-0 11:15:40] (ProviderManager.java:doAuthentication:127) Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
      [DEBUG] [btpool0-0 11:15:41] (AbstractAuthenticationProcessingFilter.java:unsuccessfulAuthentication:318) Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: users is not mapped [select h from users h where username=?]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: users is not mapped [select h from users h where username=?]
      [DEBUG] [btpool0-0 11:15:41] (AbstractAuthenticationProcessingFilter.java:unsuccessfulAuthentication:319) Updated SecurityContextHolder to contain null Authentication
      [DEBUG] [btpool0-0 11:15:41] (AbstractAuthenticationProcessingFilter.java:unsuccessfulAuthentication:320) Delegating to authentication failure handlerorg.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@163b3ec
      [DEBUG] [btpool0-0 11:15:41] (SimpleUrlAuthenticationFailureHandler.java:onAuthenticationFailure:67) Redirecting to /login.jsp

      Comment


      • #4
        The error indicates that your select statement says to select from users, but your class is User. I suggest you write some tests to verify that your UserDaoImpl is working first. After that you should try to plug it into Spring Security.

        PS: Looking at your hibernate code it appears you are using String concatenation instead of parameterizing your query. This can lead to SQL injection attacks. I'm not sure if you have since fixed this issue since the query looks to be using params, but you may want to ensure you correct this.

        Comment


        • #5
          I solved the issue, The problem was that I was importing the Entity and Table class from org.hibernate.annotations instead of javax.persistence. After changing that, I got some errors but I fixed them and it now works.

          Comment


          • #6
            Hi guys, I have a very similar app and the same problem.
            I'm using Spring MVC, Spring Security, Hibernate (Hibernate Template), and CustomUserDetailsService to retrieve and validate the users from database.

            The @Autowire is not working inside my CustomUserDetailsService . The properties that should autowired returns null.
            In my tests I tryed to use the classes without the @Autowire (using the new MyDao() ou new new MyService() directly) .In this case seems that my Hibernate session is null.
            In other test, I disabled the Security and call the hibernate methods that retrieves the users from database and then works...

            Any trip to solve this?
            Thanks


            WEB.XML
            Code:
            (...)
            <context-param>
            		<param-name>contextConfigLocation</param-name>
            		<param-value>
            			/WEB-INF/spring/root-context.xml
            			/WEB-INF/spring/spring-security.xml
            		</param-value>
            	</context-param>
            
            	<listener>
            		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            	</listener>
            
            
            	<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> 
            	
            
            	<servlet>
            		<servlet-name>suport</servlet-name>
            		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            		<init-param> 
            			<param-name>contextConfigLocation</param-name> 
            			<param-value>
            			/WEB-INF/spring/app-config.xml
            			/WEB-INF/spring/spring-security.xml
            			</param-value> 
            		</init-param>
            		<load-on-startup>1</load-on-startup>
            	</servlet>
            
            	<servlet-mapping>
            		<servlet-name>suport</servlet-name>
            		<url-pattern>/</url-pattern>
            	</servlet-mapping>
            
            (...)
            app-config.xml
            Code:
            (...)
            	<context:component-scan base-package="com.xxx"  />	
            	<mvc:annotation-driven />
                    <import resource="db-config.xml" />
            (...)
            db-config.xml
            Code:
            (...)
            	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                    <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
                    <property name="url"><value>jdbc:mysql://localhost/xxx</value></property>
                    <property name="username"><value>root</value></property>
                    <property name="password"><value>pass</value></property>
                    </bean>
                
                
                 <!-- Hibernate SessionFactory -->
                <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                    <property name="dataSource"><ref local="dataSource"/></property>
                     <property name="packagesToScan" value="com.xxx.domain" />
                    <property name="hibernateProperties">
            	        <props>
            	            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            	            <prop key="hibernate.show_sql">true</prop>
            				<!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
            	        </props>
                    </property>
                    <property name="entityInterceptor">
                		<bean class="com.xxx.util.base.HibernateInterceptor"/>
              		</property>
                    
                </bean>
            	
            	<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
            	<tx:annotation-driven/>
                <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                    <property name="sessionFactory"><ref local="sessionFactory"/></property>
                </bean>
                
                <mvc:interceptors>
            	    <bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
            	        <property name="sessionFactory">
            	            <ref local="sessionFactory" />
            	        </property>
            	    </bean>
            	</mvc:interceptors>
                
            
            (...)

            spring-security.xml
            Code:
            	<http pattern="/login" security="none" />
            	<http pattern="/resources/**" security="none" />
            	
            	<http auto-config="true" use-expressions="true" >
            		
            	        <intercept-url pattern="/login"  access="permitAll" />
            		<intercept-url pattern="/logout" access="permitAll" />
            		<intercept-url pattern="/denied" access="hasRole('ROLE_USER')" />
            		<intercept-url pattern="/"       access="hasRole('ROLE_USER')" />
            		<intercept-url pattern="/user"   access="hasRole('ROLE_USER')" />
            		<intercept-url pattern="/admin"  access="hasRole('ROLE_ADMIN')" />
            		
            		<form-login login-page="/login" authentication-failure-url="/login/failure"	default-target-url="/" />
            		<access-denied-handler error-page="/denied" />
            		<logout invalidate-session="true" logout-success-url="/logout/success"		logout-url="/logout" />
            	</http>
            	
              	
            	<beans:bean id="myUserDetailsService"
            		class="com.vsm.service.acesso.impl.CustomUserDetailsService">
            	</beans:bean>
            	
            	<beans:bean id="daoAuthenticationProvider"
            	 class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
            	  <beans:property name="userDetailsService" ref="myUserDetailsService"/>
            	</beans:bean>
            	
            	<beans:bean id="authenticationManager"
            	    class="org.springframework.security.authentication.ProviderManager">
            	  <beans:property name="providers">
            	    <beans:list>
            	      <beans:ref local="daoAuthenticationProvider" />
            	    </beans:list>
            	  </beans:property>
            	</beans:bean>
            	
            	<authentication-manager>
            	  <authentication-provider user-service-ref="myUserDetailsService">
            	    
            	  </authentication-provider>
            	</authentication-manager>
            	
            	
            (...)

            Comment


            • #7
              I solved my issue. In my case i removed from the app-config.xml the configurations related to hibernate and related to annotation configuration and put them in root-context.xml.
              This discussion helpme too:
              http://stackoverflow.com/questions/7...-child-context

              Comment

              Working...
              X