Search code examples
javaspringspring-mvcspring-securityspring-mybatis

how to get user info from jdbc user service


i am using spring security authorization to secure user login to my application by using the following code:

<jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT username, password as password,1 as enabled FROM users  WHERE username=?" authorities-by-username-query="SELECT username, authority,1 as enabled FROM users WHERE username =?" />

is there any way to add other fields to this query ex:ID,Email ... ?


Solution

  • If you want to load complete Custom user object from database, and then to set it in SecurityContextHolder/Session, the better approach would be to use custom UserDetailService

    Create a Custom user Entity:

    First create a simple Custom user Entity according to your database table

    @Entity
    @Table(name = "users")
    public class SecurityUser implements Serializable{  
    
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        @Id
        @Column(name = "username", nullable = false, unique = true)
        private String username;
    
        @Column(name = "password", nullable = false)
        @NotNull
        private String password;
    
        @Column(name = "type", nullable = false)
        @NotNull
        private String type;
    
        @Column(name = "full_name", nullable = false)
        @NotNull
        private String fullName;
    
        @Column(name = "email", nullable = false)
        @NotNull
        private String email;
    
        //Gettters & Setters plus Default constructor
    }
    

    Create a repository/DAO for accessing above User from database

    @Repository
    public interface UserRepository extends JpaRepository<SecurityUser, Long> {
        SecurityUser findByUsername(String username);
    }
    

    Create a custom user object for logged in user extending Spring's User

    public class CurrentUser extends User {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private SecurityUser securityUser;
    
        public CurrentUser(SecurityUser securityUser) {
            super(securityUser.getUsername(), securityUser.getPassword(), AuthorityUtils.createAuthorityList(securityUser.getRole().toString()));
            this.securityUser = securityUser;
        }
    
        public SecurityUser getSecurityUser() {
            return securityUser;
        }
    
        public String getRole() {
            return securityUser.getRole();
        }
    }
    

    Create a Custom User Detail Service

    @Service
    public class CurrentUserDetailsService implements UserDetailsService {
    
        @Autowired
        private UserRepository userService;
    
        @Autowired
        public CurrentUserDetailsService(UserRepository userService) {
            this.userService = userService;
        }
    
        public CurrentUserDetailsService() {
    
        }
    
        @Override
        public CurrentUser loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
            SecurityUser user = userService.findByUsername(username);
            return new CurrentUser(user);
        }
    }
    

    Set UserDetailService in Configuration

    As you are using XML based configuration, so do something like this in config file:

    <bean id="myUserDetailsService"
      class="complete-path-to-serviceClasss.MyUserDetailsService"/>
    
    <security:authentication-manager>
        <security:authentication-provider
          user-service-ref="myUserDetailsService" >
            <security:password-encoder ref="passwordEncoder">
            </security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>
    

    Now anywhere, if you execute below lines when user is loggedin, it will give you CurrentUser object with all data

    CurrentUser user = SecurityContextHolder.getContext().getAuthentication().getPrincipal()