NIHVIVO-2601 Create internal login for systems that only reveal the external authentication.

This commit is contained in:
j2blake 2011-05-11 16:02:43 +00:00
parent 53c3c982bb
commit 7fed5babcf
6 changed files with 201 additions and 0 deletions

View file

@ -1055,6 +1055,15 @@
<url-pattern>/programLogin</url-pattern> <url-pattern>/programLogin</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet>
<servlet-name>adminLogin</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.authenticate.AdminLoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>adminLogin</servlet-name>
<url-pattern>/admin/login</url-pattern>
</servlet-mapping>
<servlet> <servlet>
<servlet-name>logout</servlet-name> <servlet-name>logout</servlet-name>
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.Logout</servlet-class> <servlet-class>edu.cornell.mannlib.vitro.webapp.controller.edit.Logout</servlet-class>

View file

@ -0,0 +1,133 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.INTERNAL;
import java.util.HashMap;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
/**
* Provide a "hidden" login page for systems where the Login Widget has been
* modified to only show the link to an External Authentication system.
*
* This page is only hidden because there is no link to it. Anyone who knows the
* URL can come here, but they need to pass Internal Authentication to proceed.
*/
public class AdminLoginController extends FreemarkerHttpServlet {
public static final String PARAMETER_USERNAME = "username";
public static final String PARAMETER_PASSWORD = "password";
public static final String PARAMETER_NEW_PASSWORD = "newPassword";
public static final String URL_THIS = "/admin/login";
public static final String URL_HOME_PAGE = "/";
public static final String TEMPLATE_NAME = "adminLogin.ftl";
private static final String MESSAGE_NO_USERNAME = "errorNoUser";
private static final String MESSAGE_NO_PASSWORD = "errorNoPassword";
private static final String MESSAGE_LOGIN_FAILED = "errorLoginFailed";
private static final String MESSAGE_NEW_PASSWORD_REQUIRED = "newPasswordRequired";
@Override
protected Actions requiredActions(VitroRequest vreq) {
return Actions.EMPTY; // No requirements to use this page.
}
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
return new Core(vreq).process();
}
/**
* A threadsafe holder for the controller logic.
*/
private static class Core {
private final Authenticator auth;
private final String username;
private final String password;
private final String newPassword;
public Core(VitroRequest vreq) {
this.auth = Authenticator.getInstance(vreq);
this.username = nonNull(vreq.getParameter(PARAMETER_USERNAME));
this.password = nonNull(vreq.getParameter(PARAMETER_PASSWORD));
this.newPassword = nonNull(vreq
.getParameter(PARAMETER_NEW_PASSWORD));
}
public ResponseValues process() {
if (username.isEmpty() && password.isEmpty()) {
return showInitialForm();
}
if (username.isEmpty()) {
return showFormWithMessage(MESSAGE_NO_USERNAME);
}
if (password.isEmpty()) {
return showFormWithMessage(MESSAGE_NO_PASSWORD);
}
if (newPasswordRequired() && newPassword.isEmpty()) {
return showFormWithMessage(MESSAGE_NEW_PASSWORD_REQUIRED);
}
boolean loggedIn = tryToLogin();
if (loggedIn) {
return goToHomePage();
}
return showFormWithMessage(MESSAGE_LOGIN_FAILED);
}
private boolean newPasswordRequired() {
return auth.isCurrentPassword(username, password)
&& auth.isPasswordChangeRequired(username);
}
private boolean tryToLogin() {
if (auth.isCurrentPassword(username, password)) {
auth.recordLoginAgainstUserAccount(username, INTERNAL);
if (auth.isPasswordChangeRequired(username)) {
auth.recordNewPassword(username, newPassword);
}
return true;
} else {
return false;
}
}
private ResponseValues showInitialForm() {
Map<String, Object> body = new HashMap<String, Object>();
body.put("controllerUrl", UrlBuilder.getUrl(URL_THIS));
body.put("username", "");
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
private ResponseValues showFormWithMessage(String messageCode) {
Map<String, Object> body = new HashMap<String, Object>();
body.put("controllerUrl", UrlBuilder.getUrl(URL_THIS));
body.put("username", username);
body.put(messageCode, Boolean.TRUE);
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
private ResponseValues goToHomePage() {
return new RedirectResponseValues(URL_HOME_PAGE);
}
private String nonNull(String s) {
return (s == null) ? "" : s;
}
}
}

View file

@ -72,6 +72,11 @@ public abstract class Authenticator {
*/ */
public abstract List<String> getAssociatedIndividualUris(String username); public abstract List<String> getAssociatedIndividualUris(String username);
/**
* Is a password change needed when the user logs in?
*/
public abstract boolean isPasswordChangeRequired(String username);
/** /**
* Record a new password for the user. * Record a new password for the user.
*/ */

View file

@ -71,6 +71,16 @@ public class BasicAuthenticator extends Authenticator {
return md5NewPassword.equals(user.getMd5password()); return md5NewPassword.equals(user.getMd5password());
} }
@Override
public boolean isPasswordChangeRequired(String username) {
User user = getUserDao().getUserByUsername(username);
if ((user != null) && (user.getLoginCount() == 0)) {
return true;
} else {
return false;
}
}
@Override @Override
public void recordNewPassword(String username, String newClearTextPassword) { public void recordNewPassword(String username, String newClearTextPassword) {
User user = getUserByUsername(username); User user = getUserByUsername(username);

View file

@ -193,4 +193,10 @@ public class AuthenticatorStub extends Authenticator {
"AuthenticatorStub.recordLoginWithoutUserAccount() not implemented."); "AuthenticatorStub.recordLoginWithoutUserAccount() not implemented.");
} }
@Override
public boolean isPasswordChangeRequired(String username) {
throw new RuntimeException(
"AuthenticatorStub.isPasswordChangeRequired() not implemented.");
}
} }

View file

@ -0,0 +1,38 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for the Fake External Authentication page. -->
<section role="region">
<h2>Internal Login</h2>
<#if errorNoUser??>
<h3>No username supplied.</h3>
</#if>
<#if errorNoPassword??>
<h3>No password supplied</h3>
</#if>
<#if errorLoginFailed??>
<h3>Username or Password was incorrect.</h3>
</#if>
<#if newPasswordRequired??>
<h3>This is your first time logging in. You must supply a new password.</h3>
</#if>
<p>
Enter the username and password for your internal VIVO account.
</p>
<form action="${controllerUrl}">
<div> Username: <input type="text" name="username" value="${username}"/> </div>
<div> Password: <input type="text" name="password" /> </div>
<#if newPasswordRequired??>
<div>New Password: <input type="text" name="newPassword" /> </div>
</#if>
<input type="submit" value="submit" />
</form>
</section>