package ae.dxbpolice.eps.business.service.security.filter; import ae.dxbpolice.eps.business.ServiceLocator; import ae.dxbpolice.eps.business.datatype.DestinationApplication; import ae.dxbpolice.eps.business.datatype.LoginStatus; import ae.dxbpolice.eps.business.vo.sso.SingleSignOnVO; import ae.dxbpolice.eps.business.service.security.exception.SSOAuthenticationException; import java.io.IOException; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.acegisecurity.Authentication; import org.acegisecurity.AuthenticationException; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter; /** * Description: * CustomAuthenticationProcessingFilter is mainly used to implement the custom SSO * as when the user will be logged in from other system then it will try to access * this system it will post the j_username, j_password, and j_sso_id. and it will * use the j_sso_id to load the associated SSO_REQUEST record and check if it is * a valid request or not if true it will create the authentication Request and * make the authenticaion against the authentication manager. * * By this we will be simulationg the minimum SSO functionality and acegi will be * employeed and this system will be logged in to the J2EE container. * * Copyright 2008 I-Soft. * * @author Ali Abdel-Aziz * @version 1.0 * @since 21/05/2008 */ public class CustomAuthenticationProcessingFilter extends AuthenticationProcessingFilter { // Static fields/initializers ===================================================================================== public static final String ACEGI_SECURITY_FORM_SSO_ID_KEY = "j_sso_id"; /** * overided to make any special processing different than the normal behaviour. * like loading the username, password or both from the database if they are * not sent. * * @throws org.acegisecurity.AuthenticationException * @return Authentication * @param request * * @author Ali Abdel-Aziz */ public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { // String username = obtainUsername(request); // String password = obtainPassword(request); String ssoId = obtainSSOId(request); if (ssoId == null) { ssoId = "-1"; } ssoId = ssoId.trim(); SingleSignOnVO ssoVO = ServiceLocator.instance().getSecurityService().getSpecificSSORequest(Long.valueOf(ssoId)); String username = obtainUsername(ssoVO); String password = obtainPassword(ssoVO); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Place the last username attempted into HttpSession for views request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); // Allow subclasses to set the "details" property setDetails(request, authRequest); Authentication authentication = this.getAuthenticationManager().authenticate(authRequest); if(authentication != null ) { this.onPostAuthentication(request); } return authentication; } /** * * @throws java.io.IOException * @throws org.acegisecurity.AuthenticationException * @param request * * @author Ali Abdel-Aziz */ protected void onPreAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException,IOException { if (!validAuthenticationRequest(request,response)) { // this exception will be caught from acegi-xml and will be redirected to the login page. throw new SSOAuthenticationException(); } } /** * change the SSO_REQUEST login status from NEW_REQUEST to SUCCESS_LOGIN * * @throws java.lang.Exception * @param response * @param request */ protected void onPostAuthentication(HttpServletRequest request) throws AuthenticationException { String ssoId = obtainSSOId(request); if (ssoId == null) { ssoId = "-1"; } ssoId = ssoId.trim(); SingleSignOnVO ssoVO = ServiceLocator.instance().getSecurityService().getSpecificSSORequest(Long.valueOf(ssoId)); if(ssoVO != null && ssoVO.getLoginStatus().equals(LoginStatus.NEW_REQUEST)) { ssoVO.setLoginStatus(LoginStatus.SUCCESS_LOGIN); ssoVO.setLoginDate(new Date()); ServiceLocator.instance().getSecurityService().updateSSORequest(ssoVO); } } /** * ? EPS system will validate the SSO parameters sent by EMS system as following: - * o User ID, SSO ID, work group ID, and position ID must have * a related record in SSO table with destination field equals EPS. * o Request status must be 1 (new request). * o Login date must be null. * o Request date must be less than current date. * o Difference between current date and request date must not exceed * SSO timeout value (configurable) which means that the user request must be received within few seconds or it will be rejected. * * @return * @param response * @param request * * @author Ali Abdel-Aziz */ private boolean validAuthenticationRequest(HttpServletRequest request, HttpServletResponse response) { String ssoId = obtainSSOId(request); if (ssoId == null || ssoId.equalsIgnoreCase("")) { return false; } ssoId = ssoId.trim(); SingleSignOnVO ssoVO = ServiceLocator.instance().getSecurityService().getSpecificSSORequest(Long.valueOf(ssoId)); if(ssoVO != null && ssoVO.getLoginStatus().equals(LoginStatus.NEW_REQUEST) && ssoVO.getLoginDate() == null && ssoVO.getDestination().equals(DestinationApplication.EPS)) { return true; } else { return false; } } /** * @param request so that request attributes can be retrieved * * @return the j_sso_id that will be used to handle the Single SignOn by * verifying that there is record in the SSO_REQUEST table matching the j_sso_id. * */ protected String obtainSSOId(HttpServletRequest request) { return request.getParameter(ACEGI_SECURITY_FORM_SSO_ID_KEY); } /** * Enables subclasses to override the composition of the password, such as by including additional values * and a separator.
This might be used for example if a postcode/zipcode was required in addition to the
* password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
* AuthenticationDao will need to generate the expected password in a corresponding manner.
Authentication request token to the
* AuthenticationManager
*/
protected String obtainPassword(SingleSignOnVO ssoVO) {
return ServiceLocator.instance().getSecurityService().getUserDetails(ssoVO.getUser().getUsername()).getPassword();
}
/**
* Enables subclasses to override the composition of the username, such as by including additional values
* and a separator.
*
* @param ssoVO so that SingleSignOnVO attributes can be retrieved
*
* @return the username that will be presented in the Authentication request token to the
* AuthenticationManager
*/
protected String obtainUsername(SingleSignOnVO ssoVO) {
return ssoVO.getUser().getUsername();
}
}