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?
Asked
Active
Viewed 7.6k times
69
-
See http://stackoverflow.com/questions/2318467/how-do-i-configure-spring-security-2-database-authentication-with-hibernate-3-ann – axtavt Apr 21 '10 at 13:33
3 Answers
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>

Paul Gregoire
- 9,715
- 11
- 67
- 131

Kdeveloper
- 13,679
- 11
- 41
- 49
-
3Thanks 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 ?? – newbie Apr 24 '10 at 10:06
-
1You’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. – Kdeveloper Apr 24 '10 at 20:12
-
1you migh also want to check use the non deprecated method of user http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/User.html – Necronet Mar 03 '11 at 16:52
-
2How 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 – Nehal Damania May 19 '12 at 06:49
-
-
Thanks @Kdeveloper for sharing this code. At what point and how do you check whether the password entered by the user on the login form matches with the one (it's hash value, of course) from the database? Thanks! – Nikola Jul 12 '12 at 12:23
-
2@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. – newbie Sep 11 '12 at 07:58
-
@Necronet: refering to your comment. code becomes: User user = new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); – Adriano Oct 05 '12 at 16:43
-
7`GrantedAuthorityImpl` is deprecated, use `SimpleGrantedAuthority` instead – Carlos Oct 06 '12 at 21:00
-
@newbie: I've provided an answer below which greatly simplifies the accepted answer. You don't really need to configure a custom authentication-provider in order to authenticate against a database accessible via JDBC. Spring Security provides a way to query the database directly with 9 lines of XML. – Alessandro Giannone Apr 02 '14 at 18:09
-
@Carlos can you provide some edit/improvement on SimpleGrantedAuthority? – Timeless Mar 05 '15 at 08:24
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.

Alessandro Giannone
- 885
- 1
- 10
- 27
-
-
1You should be able to hash passwords using
in the 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 – Alessandro Giannone Feb 26 '15 at 20:50
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);
}
}

petter
- 1,765
- 18
- 22