Announcement Announcement Module
Collapse
No announcement yet.
How to store user in the HttpSession on login? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to store user in the HttpSession on login?

    Hi,

    I'm implementing my own UserDetailsService to validate login process against the database users. I'm using spring 3.0.7., with Spring security 3.0.7. I have a entity SystemUser, from which I create UserDetail entity needed in Spring Security.

    PHP Code:
    package com.objectverse.system.login.service;

    import java.util.ArrayList;
    import java.util.Collection;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.dao.DataAccessException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.GrantedAuthorityImpl;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import com.objectverse.system.login.repository.UserDetailsDao;
    import com.objectverse.system.users.user.model.SystemUser;

    @
    Service("userDetailsService")
    public class 
    UserDetailsServiceImpl implements UserDetailsService {
        
        private static 
    Log logger LogFactory.getLog(UserDetailsServiceImpl.class);
        
        @
    Autowired
        
    private UserDetailsDao userDetailsDao;
        
        @
    Override
        
    @Transactional
        
    public UserDetails loadUserByUsername(String username)
                
    throws UsernameNotFoundExceptionDataAccessException {
            if (
    logger.isDebugEnabled()) {
                
    logger.debug("UserDetailsServiceImpl::getSystemUSer");
            }
            
            
    SystemUser systemUser this.userDetailsDao.findByUsername(username);
            if (
    systemUser != null) {
                
    //RequestContextHolder.currentRequestAttributes().setAttribute("profile", systemUser, RequestAttributes.SCOPE_SESSION);

                            // In this point I'd like to store the systemUser in httpSession or any object available throughout the application (session scope).


                
    boolean accountNonExpired systemUser.getActive();
                
    boolean credentialsNonExpired systemUser.getActive();
                
    boolean accountNonLocked systemUser.getActive();
                
                
    Collection<GrantedAuthorityauthorities = new ArrayList<GrantedAuthority>();
                
    authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
                
                
    User user = new User(
                            
    systemUser.getUsername(), systemUser.getPassword(), systemUser.getActive(), 
                            
    accountNonExpiredcredentialsNonExpiredaccountNonLockedauthorities);
                return 
    user;
                
            }
            throw new 
    RuntimeException("Access denied.");
        }
            


    My config
    PHP Code:
    <security:http auto-config="true" use-expressions="true">
            <
    security:intercept-url pattern="/app/login*" access="permitAll"/>
            <
    security:intercept-url pattern="/app/signin" access="permitAll"/>
            <
    security:intercept-url pattern="/app/**" access="isAuthenticated()"/>
               <
    security:intercept-url pattern="/**" access="permitAll" />
            <
    security:form-login login-page="/app/login.jsp" authentication-failure-url="/app/login.jsp?error=failed" default-target-url="/app/desktop"/>
            <
    security:logout logout-url="/app/logoff" logout-success-url="/app/login"/>
               <
    security:session-management>
                <
    security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
            </
    security:session-management>
        </
    security:http>

        <
    bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
              <
    property name="userDetailsService" ref="userDetailsService"/>
        </
    bean>

        <
    bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
              <
    property name="providers">
                <list>
                    <
    ref local="daoAuthenticationProvider" />
                </list>
              </
    property>
        </
    bean>

        <
    security:authentication-manager>
              <
    security:authentication-provider user-service-ref="userDetailsService">
                <
    security:password-encoder hash="plaintext"/>
              </
    security:authentication-provider>
        </
    security:authentication-manager
    I have 3 questions regarding my configuration:

    1. As commented in the code I'd like to store my systemUser in httpSession or any object available throughout the application (session scope). How can I do that as the method is in the service layer and the bean is initialized when the application starts.

    2. How can I handle Exceptions? If an exception occurs I get a page with stacktrace?

    3. I'd like to add some logic where the system checks if there are any users in the database - the user is redirected to desktop and if there is no user in the database, the user is redirected to install.

    Any help appreciated.

    Bojan

  • #2
    Trust me you don't... I suggest a read on how spring security works and which components do what in Spring Security at least for 1 and 2. for 3 use a separate filter.

    Comment


    • #3
      Hi

      I have a question. This is not actually related to your issue. I'm trying to get spring security working with my mvc app.
      I have a preatty similar setup as you do. There are some differences in the userDetailsService, I use (or should i say want to use) a CRUDRepository to access the user information. The class Customer extends UserDetails.

      Code:
      @Service("userDetailsService")
      public class UserDetailsServiceImpl implements UserDetailsService {
      
      	private Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
      
      	@Autowired
      	CustomerRepository customerRep;
      
      	@Override
      	@Transactional(readOnly = true)
      	public UserDetails loadUserByUsername(String username)
      			throws UsernameNotFoundException {
      		log.debug("Getting user for username " + username);
      		Customer customer = customerRep.findByUsername(username);
      		if(customer == null){
      			throw new UsernameNotFoundException("Username " + username + " not found.");
      
      		}
      		return customer;
      	}
      }
      My security.xml

      Code:
      <?xml version="1.0" encoding="UTF-8"?>
      
      <!-- - Sample namespace-based 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.xsd">
      
      	<global-method-security pre-post-annotations="enabled">
      		<!-- AspectJ pointcut expression that locates our "post" method and applies 
      			security that way <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" 
      			access="ROLE_TELLER"/> -->
      	</global-method-security>
      
      	<http auto-config='true' use-expressions="true">
      		<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
      		<intercept-url pattern="/**" access="ROLE_USER" />
      		<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">
      		</authentication-provider>
      	</authentication-manager>
      </beans:beans>
      For some reason that I haven't yet figured out, I can't get this setup working. I get this error:

      Code:
      Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userDetailsService' is defined
      	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:529)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
      	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
      	... 94 more
      I'm probably missing some configuration, some detail. Since you have such a similar setup I was hoping you ran into this issue already.

      I hope you can help me, otherwise I'll post this in a new thread.

      Comment


      • #4
        Judging by your code, you should have something similar to below in your configurations,

        Code:
        <context:component-scan base-package="bla bla"/>

        Comment


        • #5
          Originally posted by Marten Deinum View Post
          Trust me you don't... I suggest a read on how spring security works and which components do what in Spring Security at least for 1 and 2. for 3 use a separate filter.
          So, if I understood correctly, I should just use UserDetail from the Spring Security and load SystemUser on demand, when I need it? The case is that the SystemUser is quite complex - it is connected with profile configuration, resource configuration etc, which take some time to load...

          Comment


          • #6
            My mistake - I've just seen UserDetails is an interface. So I added Interface definitions to my SystemUser and replaced the code where I retrieve a SystemUser from session. Everything works now.

            I still have problems with the failed login. Instead of displaying custom form, with an error message I get stacktrace.
            I'm going back to tutorials, hope I'll found a problem.

            Best regards,
            Bojan

            Comment


            • #7
              Originally posted by amiladomingo View Post
              Judging by your code, you should have something similar to below in your configurations,

              Code:
              <context:component-scan base-package="bla bla"/>
              I have that, that's what bothers me. I believe that it's a config order thing, but i'm going to create a thread about it. Anyway, thank you for your help

              Comment

              Working...
              X