LoginHandler.java
/*
* $Source$
* $Revision$
*
* Copyright (C) 2000 William Chesters
*
* Part of Melati (http://melati.org), a framework for the rapid
* development of clean, maintainable web applications.
*
* Melati is free software; Permission is granted to copy, distribute
* and/or modify this software under the terms either:
*
* a) the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version,
*
* or
*
* b) any version of the Melati Software License, as published
* at http://melati.org
*
* You should have received a copy of the GNU General Public License and
* the Melati Software License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
* GNU General Public License and visit http://melati.org to obtain the
* Melati Software License.
*
* Feel free to contact the Developers of Melati (http://melati.org),
* if you would like to work out a different arrangement than the options
* outlined here. It is our intention to allow Melati to be used by as
* wide an audience as possible.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact details for copyright holder:
*
* William Chesters <williamc At paneris.org>
* http://paneris.org/~williamc
* Obrechtstraat 114, 2517VX Den Haag, The Netherlands
*/
package org.melati.login;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import org.melati.Melati;
import org.melati.poem.AccessPoemException;
import org.melati.poem.Field;
import org.melati.poem.PoemThread;
import org.melati.poem.User;
import org.melati.poem.UserTable;
import org.melati.servlet.Form;
import org.melati.servlet.TemplateServlet;
import org.melati.template.ServletTemplateContext;
import org.melati.util.HttpServletRequestParameters;
import org.melati.util.MD5Util;
import org.melati.util.UTF8URLEncoder;
/**
* An object which sets up the login process.
*
*/
public class LoginHandler {
static int ONEYEARINSECONDS = 60 * 60 * 24 * 365;
protected TemplateServlet servlet;
/**
* Constructor.
*
* @param servlet to set
*/
public LoginHandler(TemplateServlet servlet) {
this.servlet = servlet;
}
protected String loginTemplate(String name) {
/*
// Fails to find templates in jars!!
return "org" + File.separatorChar +
"melati" + File.separatorChar +
"login" + File.separatorChar +
name;
*/
return "org/melati/login/" + name;
}
protected String loginPageTemplate() {
return loginTemplate("Login");
}
protected String usernameUnknownTemplate() {
return loginTemplate("LoginFailure");
}
protected String passwordIncorrectTemplate() {
return loginTemplate("LoginFailure");
}
protected String loginSuccessTemplate () {
return loginTemplate("LoginSuccess");
}
/**
* Extract current values from context and add fields to context.
*
* @param context the ServletTemplateContext to modify
*/
public void setupContext(ServletTemplateContext context) {
HttpSession session = context.getSession();
AccessPoemException triggeringException = null;
if (session != null) triggeringException =
(AccessPoemException)session.getAttribute(Login.TRIGGERING_EXCEPTION);
if (triggeringException != null)
context.put("triggeringException", triggeringException);
String username = context.getFormField("field_login");
String password = context.getFormField("field_password");
UserTable<User> users = PoemThread.database().getUserTable();
context.put("login", new Field<String>(username, users.getLoginColumn()));
context.put("password", new Field<String>(password, users.getPasswordColumn()));
context.put("loginUnknown", Boolean.FALSE);
context.put("passwordWrong", Boolean.FALSE);
}
/**
* Set cookies if requested, remove any leftovers from any
* triggering {@link AccessPoemException}.
*
* @param melati the melati
* @param templateContext context to augment
* @param user the established User
* @return the name of the success template
*/
public String loginSuccessfullyAs (Melati melati,
ServletTemplateContext templateContext,
User user) {
// Arrange for the original parameters from the request that triggered the
// login to be overlaid on the next request that comes in if it's a match
// (this allows POSTed fields to be recovered without converting the
// request into a GET that the browser will repeat on reload without giving
// any warning).
// if we have asked that our password be remembered, set the cookies
if (Form.getFieldNulled(templateContext,"rememberme") != null) {
String ldb = melati.getPoemContext().getLogicalDatabase();
melati.getResponse().addCookie(makeCookie(ldb, user.getLogin_unsafe()));
melati.getResponse().addCookie(makeCookie(ldb+user.getLogin_unsafe(),
MD5Util.encode(user.getPassword_unsafe())));
}
HttpSession session = templateContext.getSession();
HttpServletRequestParameters triggeringParams =
(HttpServletRequestParameters)session.getAttribute(
Login.TRIGGERING_REQUEST_PARAMETERS);
if (triggeringParams != null) {
session.setAttribute(HttpSessionAccessHandler.OVERLAY_PARAMETERS,
triggeringParams);
session.removeAttribute(Login.TRIGGERING_REQUEST_PARAMETERS);
session.removeAttribute(Login.TRIGGERING_EXCEPTION);
templateContext.put("continuationURL",
triggeringParams.continuationURL());
} else {
if (Form.getFieldNulled(templateContext,"continuationURL")
!= null) {
templateContext.put("continuationURL",
templateContext.getFormField("continuationURL"));
}
}
session.setAttribute(HttpSessionAccessHandler.USER, user);
return loginSuccessTemplate();
}
/**
* Make a cookie, using default (UTF-8) encoding, regardless of user's
* encoding.
*/
private Cookie makeCookie(String key, String value) {
Cookie c = new Cookie(UTF8URLEncoder.encode(key), UTF8URLEncoder.encode(value));
c.setPath("/");
c.setMaxAge(ONEYEARINSECONDS);
c.setComment("This cookie is used to automatically log you back into " +
"this site when you return.");
return c;
}
/**
* Action the login.
*
* @param melati the Melati
* @param templateContext the context
* @return a template name
* @throws Exception
*/
public String doTemplateRequest(Melati melati,
ServletTemplateContext templateContext)
throws Exception {
setupContext(templateContext);
String username = templateContext.getFormField("field_login");
String password = templateContext.getFormField("field_password");
if (username == null)
return loginPageTemplate();
User user = (User)PoemThread.database().getUserTable().getLoginColumn().
firstWhereEq(username);
if (user == null) {
templateContext.put("loginUnknown", Boolean.TRUE);
return usernameUnknownTemplate();
}
if (!user.getPassword_unsafe().equals(password)) {
templateContext.put("passwordWrong", Boolean.TRUE);
return passwordIncorrectTemplate();
}
return loginSuccessfullyAs(melati, templateContext, user);
}
}