I tried searching in Google, but I could not find any good examples where a username and password are checked with a database for authentication purposes.
In further simple words, how can I create a simple login form using Spring and Hibernate where the credentials are checked with the database.
Update
Cam anyone come up with a simple example where I can see how the flow goes and how the input data is passed to hibernate?
The basic xml-configuration you can see in the post of "Easy Angle". The part he mentioned as "myUserService" is a bean that implements "UserDetailService" That one has basically just one method to implement which is the following
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException
If you use Spring, then you'll probably have a Bean, that handles the access to your User-Table. That one you can just inject into that class to retrieve User details, like:
@Override public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException { UserTable user = userbean.getUserbyName(name); if (user == null) { throw new UsernameNotFoundException("User " + name + " not found!"); } Collection<GrantedAuthority> auth = getAuthorities(user.getAuthorities()); return new User(user.getName(), user.getPassword(), true, true, true, true, auth); }
Now in an authentication bean all you need is to inject this bean and ask it for the UserDetails. There you can use it to check if the credentials are correct and if so fill the SecurityContext with the needed information in order to be logged in.
@Override public Boolean authenticate(String username, String password) { UserDetails userdetail = null; try { userdetail = myUserService.loadUserByUsername(username); } catch (UsernameNotFoundException e) { return false; } catch (DataAccessException e) { return false; } if (!myUserService.encodePassword(password).equals(userdetail.getPassword())) { return false; } Authentication auth = new UsernamePasswordAuthenticationToken(userdetail.getUsername(), userdetail.getPassword(), userdetail.getAuthorities()); SecurityContext sc = new SecurityContextImpl(); ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes(); attr.getRequest().getSession().setAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY, userdetail.getUsername()); sc.setAuthentication(auth); SecurityContextHolder.setContext(sc); return true; }
Of course thats a simplified version of the real one. There are way more checks that you have to perform prior to say that the user is authenticated (SQLInjection for instance)
At first you should define this file WEB-INF/spring/serurity-context.xml
:
<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-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"> <http auto-config="true" /> <beans:bean id="myUserService" class="org.my.UserService" /> <authentication-provider user-service-ref="myUserService" /> </beans:beans>
Now you should create org.my.UserService
class and implement interface org.springframework.security.core.userdetails.UserDetailsService
. This interface has one method:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, org.springframework.dao.DataAccessException
And in this method you can use Hibernate in order to load user by userName. If user does not exists - just throw UsernameNotFoundException, otherwise return new intialized UserDetails instance (there you can provide a lot of stuff like user roles, account expiration date, etc...).
Now comes web.xml
:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>My Webapp</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/*-context.xml </param-value> </context-param> <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> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
If you have any questions or something goes wrong, feel free to ask :)
PS: So with UserDetailsService you don't have to check password of whether user account is active, etc. You just provide spring-security information about user with provided userName
and framework validates user itself. If you encode your passwords with MD5 for example, than you can use password-encoder
like this:
<beans:bean id="myUserService" class="org.my.UserService" /> <authentication-provider user-service-ref="myUserService"> <password-encoder hash="md5"/> </authentication-provider>
Now we will dive more deeper in UserService
- my (simplified) real world example.
UserService
class:
import org.my_company.my_app.domain.User public class UserService implements UserDetailsService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { // load user User user = userDao.getUser(username); if (user != null) { // convert roles List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>(); for (Privilege p : user.getPrivileges()) { roles.add(new GrantedAuthorityImpl(p.getName())); } // initialize user SecurityUser securityUser = new SecurityUser( user.getUsername(), user.getLdapAuth() ? getLdapPassword(user.getUsername()) : user.getPassword(), user.getStatus() != User.Status.NOT_COMMITED, user.getStatus() != User.Status.BLOCKED, true, true, roles.toArray(new GrantedAuthority[0]) ); securityUser.setUser(user); return securityUser; } else { throw new UsernameNotFoundException("No user with username '" + username + "' found!"); } } }
Now SecurityUser
:
import org.my_company.my_app.domain.User public class SecurityUser extends org.springframework.security.core.userdetails.User { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public SecurityUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, GrantedAuthority[] authorities) throws IllegalArgumentException { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); } }
And finally UserDao
:
import org.my_company.my_app.domain.User public class UserDao extends HibernateDaoSupport { public User getUser(String username) { List users = getHibernateTemplate().find("from User where username = ?", username); return users == null || users.size() <= 0 ? null : (User) users.get(0); } }
As you can see I used HibernateTemplate
here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With