/**
* Copyright (c) 2004-2011 Wang Jinbao(Julian Wong), http://www.ralasafe.com
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/
package org.ralasafe.webFilter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.ralasafe.Factory;
import org.ralasafe.WebRalasafe;
import org.ralasafe.encrypt.Base64Encrypt;
import org.ralasafe.encrypt.Encrypt;
import org.ralasafe.encrypt.Md5Encrypt;
import org.ralasafe.encrypt.PlainEncrypt;
import org.ralasafe.encrypt.ShaEncrypt;
import org.ralasafe.metadata.user.FieldMetadata;
import org.ralasafe.servlet.WebUtil;
import org.ralasafe.user.User;
import org.ralasafe.user.UserManager;
import org.ralasafe.userType.UserType;
import org.ralasafe.util.StringUtil;
/**
* Check whether the user is logged in, if not, go to the login screen.
* User enters loginname(maybe many fields, like areaId and username) and password, and validated by the Filter.
* If it is validated, redirect to the former request url; Otherwise, stay in the login screen.
*
* <p>
* Config parameters:
* <ul>
* <li>loginPage: required, login page, example: /login.do</li>
* <li>uniqueFieldsParams: optional, which parameter(s) is/are corresponding to uniqueField.
* If it's not given, use uniqueFields difined in usermetadata</li>
* <li>passwordParam: optional, default value: password.</li>
* <li>userPasswordField: optional, default value: password. Which field defined in usermetadata means password</li>
* <li>encryptMethod: optional, default: no encrypt. Ralasafe provides several encryption algorithms: base64,md5hex,shahex.
* You can develop your special encrypt method. If so, config your implment class there, which should implement interface
* <code>org.ralasafe.encrypt.Encrypt</code></li>
* <li>denyMessage: optional, default value: LoginName and password not matched. If loginName & password not matched,
* Ralasafe will give this message to login user.</li>
* </ul>
* </p>
*
*
*
*/
public class LoginFilter implements Filter {
private static final String RALASAFE_REQUEST_LOGIN = "ralasafeRequestLogin";
private static final String DENY_MESSAGE = "denyMessage";
private static final String GOTO_PAGE = "gotoPage";
private String loginPage;
private String checkLoginUrlPattern;
private String[] uniqueFieldsParams;
private String passwordParam;
private String userPasswordField;
private String denyMessage;
private String successPage;
private int maxAttempts;
private String attemptMessage;
private String userAttemptField;
private String resetInterval;
private Encrypt encrypt;
// private String redirectLoginPage;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) (req);
HttpServletResponse httpResp = (HttpServletResponse) (resp);
// If the request is login screen, there's no need to filter now
if (requestForLoginPage(httpReq)) {
chain.doFilter(req, resp);
return;
}
HttpSession session = httpReq.getSession();
if (requestFromLoginPage(httpReq)) {
WebRalasafe.setCurrentUser(httpReq, null);
String gotoUrl = (String) session.getAttribute(GOTO_PAGE);
User user = validUser(httpReq, httpResp);
if (user == null) {
// validation failed, login again
gotoLoginPage(httpReq, httpResp, denyMessage, gotoUrl);
return;
} else {
// validate successfully
req.setAttribute(GOTO_PAGE, gotoUrl);
session.removeAttribute(DENY_MESSAGE);
session.removeAttribute(GOTO_PAGE);
session.removeAttribute(RALASAFE_REQUEST_LOGIN);
WebRalasafe.setCurrentUser(httpReq, user);
chain.doFilter(req, resp);
return;
}
} else {
Object user = WebRalasafe.getCurrentUser(httpReq);
if (user == null) {
// not login yet, goto login screen
session.removeAttribute(DENY_MESSAGE);
String gotoPage = httpReq.getRequestURI();
gotoLoginPage(httpReq, httpResp, null, gotoPage);
return;
} else {
chain.doFilter(req, resp);
return;
}
}
}
/**
* Does client side request for login page?
*
* @param httpReq
* @return
*/
private boolean requestForLoginPage(HttpServletRequest httpReq) {
String url = httpReq.getServletPath();
if (url.toLowerCase().startsWith(loginPage.toLowerCase())) {
// is ralasafe system direct to this page?
String flag = (String) httpReq.getSession().getAttribute(
RALASAFE_REQUEST_LOGIN);
// String flag=httpReq.getParameter( RALASAFE_REQUEST_LOGIN );
if (!"y".equalsIgnoreCase(flag)) {
HttpSession session = httpReq.getSession();
session.removeAttribute(DENY_MESSAGE);
session.removeAttribute(GOTO_PAGE);
}
return true;
}
return false;
}
/**
* Client side filled username and password, request for login.
*
* @param httpReq
* @return
*/
private boolean requestFromLoginPage(HttpServletRequest httpReq) {
String url = httpReq.getHeader("REFERER");
if (StringUtil.isEmpty(url)) {
url = httpReq.getHeader("referer");
}
String fromPath = "";
if (StringUtil.isEmpty(url)) {
fromPath = httpReq.getServletPath();
} else {
String subUrl = url.substring(url.indexOf("://") + "://".length());
String contextPath = httpReq.getContextPath();
// whether is a ROOT context. ROOT context path is "".
if( "".equals( contextPath ) ) {
fromPath = subUrl.substring( subUrl.indexOf( "/" ) );
} else {
fromPath = subUrl.substring(subUrl.indexOf(contextPath) + contextPath.length());
}
}
return fromPath.toLowerCase().startsWith(loginPage.toLowerCase());
}
private void gotoLoginPage(HttpServletRequest httpReq,
HttpServletResponse httpResp, String denyMessage, String gotoPage)
throws ServletException, IOException {
httpReq.getSession().setAttribute(RALASAFE_REQUEST_LOGIN, "y");
httpReq.getSession().setAttribute(DENY_MESSAGE, denyMessage);
httpReq.getSession().setAttribute(GOTO_PAGE, gotoPage);
httpResp.sendRedirect(httpReq.getContextPath() + loginPage);
}
private User validUser(HttpServletRequest httpReq,
HttpServletResponse httpResp) {
// convert uniqueFields to object
UserType userType = WebUtil.getUserType(httpReq);
FieldMetadata[] uniqueFields = userType.getUserMetadata()
.getMainTableMetadata().getUniqueFields();
User expectUser = new User();
for (int i = 0; i < uniqueFields.length; i++) {
FieldMetadata fieldMetadata = uniqueFields[i];
String javaType = fieldMetadata.getJavaType();
String paramName = fieldMetadata.getName();
if (uniqueFieldsParams != null) {
paramName = uniqueFieldsParams[i];
}
String rawValue = httpReq.getParameter(paramName);
Object value = parse(javaType, rawValue);
expectUser.set(fieldMetadata.getName(), value);
}
String rawPassword = httpReq.getParameter(passwordParam);
String password = encrypt.encrypt(rawPassword);
UserManager manager = Factory.getUserManager(userType.getName());
User findUser = manager.selectByUniqueFields(expectUser);
if (findUser != null
&& findUser.get(userPasswordField).equals(password)) {
return findUser;
} else {
return null;
}
}
private Object parse(String javaType, String rawValue) {
if (javaType.equalsIgnoreCase("java.lang.String")) {
return rawValue;
} else if (javaType.equalsIgnoreCase("java.lang.Integer")) {
return new Integer(rawValue);
} else if (javaType.equalsIgnoreCase("java.lang.Double")) {
return new Double(rawValue);
} else if (javaType.equalsIgnoreCase("java.lang.Float")) {
return new Float(rawValue);
}
return null;
}
public void init(FilterConfig config) throws ServletException {
String rawUniqueFieldsParams = config
.getInitParameter("uniqueFieldsParams");
if (!StringUtil.isEmpty(rawUniqueFieldsParams)) {
uniqueFieldsParams = StringUtil.splitAndTrim(rawUniqueFieldsParams,
",");
}
passwordParam = config.getInitParameter("passwordParam");
if (StringUtil.isEmpty(passwordParam)) {
passwordParam = "password";
}
userPasswordField = config.getInitParameter("userPasswordField");
if (StringUtil.isEmpty(userPasswordField)) {
userPasswordField = "password";
}
denyMessage = config.getInitParameter("denyMessage");
if (StringUtil.isEmpty(denyMessage)) {
denyMessage = "LoginName and password not matched";
}
String encryptMethod = config.getInitParameter("encryptMethod");
if (StringUtil.isEmpty(encryptMethod)) {
encrypt = new PlainEncrypt();
} else if ("base64".equalsIgnoreCase(encryptMethod)) {
encrypt = new Base64Encrypt();
} else if ("md5hex".equalsIgnoreCase(encryptMethod)) {
encrypt = new Md5Encrypt();
} else if ("shahex".equalsIgnoreCase(encryptMethod)) {
encrypt = new ShaEncrypt();
} else {
// developer customize encrypt method
try {
Object instance = Class.forName(encryptMethod).newInstance();
encrypt = (Encrypt) instance;
} catch (Exception e) {
e.printStackTrace();
throw new ServletException("Encry method not found: " + encryptMethod);
}
}
loginPage = config.getInitParameter("loginPage");
// redirectLoginPage="/"+config.getServletContext().getServletContextName()+loginPage;
// if( redirectLoginPage.indexOf( "?" )==-1 ) {
// redirectLoginPage=redirectLoginPage+"?1=1";
// }
}
}