Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring login form example

Tags:

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?

like image 837
Thalaivar Avatar asked Jan 06 '11 09:01

Thalaivar


2 Answers

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)

like image 20
Hons Avatar answered Oct 07 '22 01:10

Hons


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> 

Update

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.

like image 114
tenshi Avatar answered Oct 07 '22 01:10

tenshi