- 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 to redirect users based on their role.
* 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
*
* @author abhishek.somani
*/
public class HomeController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse arg1)
throws Exception {
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");
}
}