Objective 1 : Use Custom DAO classes in Spring Security Spring Security provides mechanism by which we can specify database queries in spring security xml file , but sometimes we want to use our own custom dao classes which are already built. Objective 2 : Forward the request to different home pages based on the authorized role First , to use your custom dao class , we have to create a bean which implements org.springframework.security.userdetails.UserDetailsService interface. Override the loadUserByUserName method of this interface. We have to create org.springframework.security.userdetails.User from our custom dao object.
package com.security;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import com.dal.interfaces.UserDAO;
import com.exceptions.DAOException;
/**
* //this class is used by spring controller to authenticate and authorize user
* modified this class to user our Database and defined user roles
*
* @author abhishek.somani
*
*/
public class UserDetailServiceImpl implements UserDetailsService {
private UserDAO userdao;
public void setUserdao(UserDAO userdao) {
this.userdao = userdao;
}
// this class is used by spring controller to authenticate and authorize
// user
@Override
public UserDetails loadUserByUsername(String userId)
throws UsernameNotFoundException {
com.model.User u;
try {
u = userdao.get(userId);
if (u == null)
throw new UsernameNotFoundException("user name not found");
} catch (DAOException e) {
throw new UsernameNotFoundException("database error ");
}
return buildUserFromUserEntity(u);
}
private User buildUserFromUserEntity(com.model.User userEntity) {
// convert model user to spring security user
String username = userEntity.getUserId();
String password = userEntity.getPassword();
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
GrantedAuthority[] authorities = new GrantedAuthorityImpl[1];
authorities[0] = new GrantedAuthorityImpl(userEntity.getRole());
User springUser = new User(username, password, enabled,
accountNonExpired, credentialsNonExpired, accountNonLocked,
authorities);
return springUser;
}
}
In Spring-security.xml we have to give reference of this bean in user-service-ref in authentication-provider tag.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
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.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.1.xsd
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- this is security configuration file which maps urls according to user roles authorization -->
<security:http auto-config="true">
<security:logout logout-success-url="/login" invalidate-session="true" logout-url="/logout"/>
<security:intercept-url pattern="/login.jsp" filters="none" />
<security:intercept-url pattern="/login" filters="none" />
<security:intercept-url pattern="/logout" filters="none" />
<security:intercept-url pattern="/Test" access="ROLE_ADMIN" />
<security:intercept-url pattern="/home" access="ROLE_ADMIN,ROLE_USER"/>
<security:intercept-url pattern="/user/*" access="ROLE_USER" />
<security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
<security:intercept-url pattern="/*" filters="none"/>
<security:form-login login-page="/login"
default-target-url="/home" authentication-failure-url="/login?error=1"
always-use-default-target="true"/>
</security:http>
<security:authentication-provider
user-service-ref="userDetailsService" />
<bean id='userDetailsService' class='com.security.UserDetailServiceImpl'>
<property name='userdao' ref='userDao' />
</bean>
</beans>
Now we want to redirect user after authentication and authorization by user. If a user has User role , it should go to home page of user or if a user has admin role then it should go to home page of admin . For this , create a simple controller .After successfull authorization and authentication request.getUserPrinicipal will have the Prinicipal object containing userName which is set in UserDetailServiceImpl and we can check the roles by request.isUserInRole method.In spring-security.xml , set target url to this controller and set always-use-default-target attribute to true in form-login tag , because we always want this controller to execute after user successfully authenticate the user. Sometimes if the request contains referer header , spring security redirect it to that previous link.That is why we set always-use-default-target attribute to true.
package com.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import com.constants.Constants;
import com.model.UserRoles;
import com.util.CustomLogger;
/**
* home controller redirects the user based on the roles
* @author abhishek.somani
*
*/
public class HomeController extends AbstractController
{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,HttpServletResponse arg1) throws Exception
{
//this is the home controller to redirect user to their home pages based on role name
// for Admin it should be /admin/home
//for user it should be /user/home
if (request.isUserInRole("ROLE_USER"))
{
request.setAttribute("appendURL", "user");
return new ModelAndView("user/home", "welcome ", null);
}
if (request.isUserInRole("ROLE_ADMIN"))
{
request.setAttribute("appendURL", "admin");
return new ModelAndView("admin/home", "welcome ", null);
}
throw new Exception("No roles Detected");
}
}
Do Comment if you face any difficulty.