68

I need to authenticate users from database, Spring Security documents don't tell how to authenticate with hibernate. Is that possible and how can I do that?

1

3 Answers 3

134

You have to make your own custom authentication-provider.

Example code:

Service to load Users from Hibernate:

import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @Service("userDetailsService") public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserDao dao; @Autowired private Assembler assembler; @Transactional(readOnly = true) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { UserDetails userDetails = null; UserEntity userEntity = dao.findByName(username); if (userEntity == null) throw new UsernameNotFoundException("user not found"); return assembler.buildUserFromUserEntity(userEntity); } } 

Service to convert your entity to a spring user object:

import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; @Service("assembler") public class Assembler { @Transactional(readOnly = true) User buildUserFromUserEntity(UserEntity userEntity) { String username = userEntity.getName(); String password = userEntity.getPassword(); boolean enabled = userEntity.isActive(); boolean accountNonExpired = userEntity.isActive(); boolean credentialsNonExpired = userEntity.isActive(); boolean accountNonLocked = userEntity.isActive(); Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); for (SecurityRoleEntity role : userEntity.getRoles()) { authorities.add(new GrantedAuthorityImpl(role.getRoleName())); } User user = new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id); return user; } } 

The namespace-based application-context-security.xml would look something like:

<http> <intercept-url pattern="/login.do*" filters="none"/> <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <form-login login-page="/login.do" authentication-failure-url="/login.do?error=failed" login-processing-url="/login-please.do" /> <logout logout-url="/logoff-please.do" logout-success-url="/logoff.html" /> </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> 
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for good and detailed answer with full code. Can you tell my why Assembler class is needed, why can't you just put that code in the loadUserByUsername method ??
You’re right, there is no real need for the Assembler. Just thought it was a good idea to keep the userDetailsService simple and make the conversion reusable via the assembler service.
How does Autowiring work for userDetailsService, my autowiring is not working. I had to define userDetailsService bean in the security xml. Any idea. Rest of the places the autowiring is working
@Nikola you don't check yourself if password (hashes) match, Spring Security does that for you automatically. If password is wrong, then Spring Security redirects to wrong password URL defined in Spring Security XML configuration. You just have to provide User object, where password is hashed by correct hashing algorithm. You can also use password salt if you want, but that requires more configuration.
GrantedAuthorityImpl is deprecated, use SimpleGrantedAuthority instead
|
4

If you're using a JDBC accessible database, then you could use the following authentication-provider and avoid creating a custom one. It cuts down the code required to 9 lines of XML:

<authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password from users where username=?" authorities-by-username-query="select u.username, r.authority from users u, roles r where u.userid = r.userid and u.username =?" /> </authentication-provider> 

You can then setup your dataSource as follows

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/DB_NAME" /> <property name="username" value="root" /> <property name="password" value="password" /> </bean> 

Have a look at this post: http://codehustler.org/blog/spring-security-tutorial-form-login/ It covers everything you need to know about customising Spring Security form-login.

2 Comments

Can we use this with hashed passwords?
You should be able to hash passwords using <password-encoder ref="encoder"/> in the <authentication-provider> tag. The encoder refers to the encoding bean you wish to use e.g. org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder. Alternatively, if you're looking to use something like SHA then you can add <password-encoder hash="sha" />
1

A java configuration could look something like this

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider .setUserDetailsService(userDetailsService); auth.authenticationProvider(daoAuthenticationProvider); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.