Spring Security for Redirecting to Multiple Views
We need to direct to different pages based upon the different users after login success.
For admin pages we need to redirect to admin.jsp after login success based upon the access ROLE_ADMIN.
For user pages we need to redirect to user.jsp after login success based upon the access ROLE_USER.
Spring security Authentication success handler is used to decide what to do after success full authentication.
DB Schema :
Create tables in the database. Two tables user and role need to be created.
Table structure for `tbl_users`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_users`;
CREATE TABLE `tbl_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(100) NOT NULL,
`password` varchar(20) NOT NULL,
`enabled` int(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Table structure for `tbl_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_user_role`;
CREATE TABLE `tbl_user_role` (
`userid` int(11) NOT NULL,
`rolename` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Role table contains the roles of the particular user.
User table contains the detail information about the user.
Spring-security.xml
<http auto-config="true">
<intercept-url pattern="/admin**" access="ROLE_ADMIN" />
<intercept-url pattern="/admin**" access="ROLE_USER" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="j_username"
password-parameter="j_password"
authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf/>
</http>
<authentication-manager>
<authentication-provider>
<!-- Select user and user_role from database -->
<jdbc-user-service data-source-ref="dataSource">
users-by-username-query="select username, password, enabled from tbl_users where username=?"
authorities-by-username-query="select u.username, r.rolename from tbl_users u, tbl_user_role r where u.id=r.userid and u.username=?"/>
</authentication-provider>
</authentication-manager>
</http>
<beans:bean id="myAuthenticationSuccessHandler"
class="com.sreemandira.satya.CustomAuthenticationSuccessHandler " />
JDBC user service implementation provides two attributes to match username with password and then username with granted role or authority.
1. users-by-username-query
2. authorities-by-username-query
authentication-success-handler-ref : This will be called after success full authentication. AuthenticationSuccessHandler interface will be called for creating custom authentication.
AuthenticationSuccessHandler will be used to provide custom implementation of success handler.
Depending upon the ROLE of the user we need to redirect to different URL.
CustomAuthenticationSuccessHandler :
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
protected Log logger = LogFactory.getLog(this.getClass());
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
boolean isUser = false;
boolean isAdmin = false;
// Access the user role after success full login
User authUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
HttpSession session = httpServletRequest.getSession();
session.setAttribute("username", authUser.getUsername());
session.setAttribute("authorities", authentication.getAuthorities());
// Set response OK.
response.setStatus(HttpServletResponse.SC_OK);
// Redirect the user based upon the user ROLE.
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
isUser = true;
break;
} else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isAdmin = true;
break;
}.
}
if (isUser) {
return "/home.html";
} else if (isAdmin) {
return "/admin.html";
} else {
throw new IllegalStateException();
}
}
}
}
Security Context will store the details of the principal currently using the application. Spring security uses Authentication to represent these information.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
Authentication :
Authentication will represent a token for an authenticated principal once the request has been processed by authenticate method of AuthenticationManager.
Once the request has been authenticated the authentication will be stored in the Thread Local of the Security Context managed by SecurityContextHolder.
Principal :
Principal will represent an entity, individual or a login id.
Granted Authority :
Granted Authority is the permission or right. Permissions are expressed as Strings.
We can grant different Granted Authorities to the users by putting them to the security context.
Roles are just "permissions" with a naming convention that a role is a GrantedAuthority that starts with the prefix ROLE_.
Granted Authority will check the ROLE and redirect to appropriate target URL based on the ROLE.
Admin user will determine the ROLE_ADMIN authority and redirect to admin page.
Home user will determine the ROLE_USER authority and redirect to home page.
We need to direct to different pages based upon the different users after login success.
For admin pages we need to redirect to admin.jsp after login success based upon the access ROLE_ADMIN.
For user pages we need to redirect to user.jsp after login success based upon the access ROLE_USER.
Spring security Authentication success handler is used to decide what to do after success full authentication.
DB Schema :
Create tables in the database. Two tables user and role need to be created.
Table structure for `tbl_users`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_users`;
CREATE TABLE `tbl_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(100) NOT NULL,
`password` varchar(20) NOT NULL,
`enabled` int(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Table structure for `tbl_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_user_role`;
CREATE TABLE `tbl_user_role` (
`userid` int(11) NOT NULL,
`rolename` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Role table contains the roles of the particular user.
User table contains the detail information about the user.
Spring-security.xml
<http auto-config="true">
<intercept-url pattern="/admin**" access="ROLE_ADMIN" />
<intercept-url pattern="/admin**" access="ROLE_USER" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="j_username"
password-parameter="j_password"
authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf/>
</http>
<authentication-manager>
<authentication-provider>
<!-- Select user and user_role from database -->
<jdbc-user-service data-source-ref="dataSource">
users-by-username-query="select username, password, enabled from tbl_users where username=?"
authorities-by-username-query="select u.username, r.rolename from tbl_users u, tbl_user_role r where u.id=r.userid and u.username=?"/>
</authentication-provider>
</authentication-manager>
</http>
<beans:bean id="myAuthenticationSuccessHandler"
class="com.sreemandira.satya.CustomAuthenticationSuccessHandler " />
JDBC user service implementation provides two attributes to match username with password and then username with granted role or authority.
1. users-by-username-query
2. authorities-by-username-query
authentication-success-handler-ref : This will be called after success full authentication. AuthenticationSuccessHandler interface will be called for creating custom authentication.
AuthenticationSuccessHandler will be used to provide custom implementation of success handler.
Depending upon the ROLE of the user we need to redirect to different URL.
CustomAuthenticationSuccessHandler :
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
protected Log logger = LogFactory.getLog(this.getClass());
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
boolean isUser = false;
boolean isAdmin = false;
// Access the user role after success full login
User authUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
HttpSession session = httpServletRequest.getSession();
session.setAttribute("username", authUser.getUsername());
session.setAttribute("authorities", authentication.getAuthorities());
// Set response OK.
response.setStatus(HttpServletResponse.SC_OK);
// Redirect the user based upon the user ROLE.
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
isUser = true;
break;
} else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isAdmin = true;
break;
}.
}
if (isUser) {
return "/home.html";
} else if (isAdmin) {
return "/admin.html";
} else {
throw new IllegalStateException();
}
}
}
}
SecurityContextHolder:
This is the location where we store the present security context of the application, which includes the details of the principal currently using the application. Security Context will use the Thread Local to store these Details. So, Security Context will always available to the methods in the same thread of execution. Even if Security Context will not be passed as an argument to the method.Security Context will store the details of the principal currently using the application. Spring security uses Authentication to represent these information.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
Authentication :
Authentication will represent a token for an authenticated principal once the request has been processed by authenticate method of AuthenticationManager.
Once the request has been authenticated the authentication will be stored in the Thread Local of the Security Context managed by SecurityContextHolder.
Principal :
Principal will represent an entity, individual or a login id.
Granted Authority :
Granted Authority is the permission or right. Permissions are expressed as Strings.
We can grant different Granted Authorities to the users by putting them to the security context.
Roles are just "permissions" with a naming convention that a role is a GrantedAuthority that starts with the prefix ROLE_.
Granted Authority will check the ROLE and redirect to appropriate target URL based on the ROLE.
Admin user will determine the ROLE_ADMIN authority and redirect to admin page.
Home user will determine the ROLE_USER authority and redirect to home page.