vivo/contrib/FLShibboleth/includes/ShibauthAdminAuthenticate.java

254 lines
13 KiB
Java
Raw Normal View History

package edu.cornell.mannlib.vitro.webapp.controller.edit;
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import edu.cornell.mannlib.vedit.beans.LoginFormBean;
import edu.cornell.mannlib.vitro.webapp.beans.User;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.dao.UserDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.LoginEvent;
import edu.cornell.mannlib.vitro.webapp.dao.jena.LoginLogoutEvent;
/*
* yxl: This is a copy of Authenticate.java and modified for Shibboleth authentication
*
*/
public class ShibauthAdminAuthenticate extends VitroHttpServlet {
private static final int DEFAULT_PORTAL_ID=1;
public static final String USER_SESSION_MAP_ATTR = "userURISessionMap";
private UserDao userDao = null;
private static final Log log = LogFactory.getLog(Authenticate.class.getName());
public void doPost( HttpServletRequest request, HttpServletResponse response ) {
try {
HttpSession session = request.getSession();
if(session.isNew()){
session.setMaxInactiveInterval(300); // seconds, not milliseconds
}
userDao = ((WebappDaoFactory)session.getServletContext().getAttribute("webappDaoFactory")).getUserDao();
LoginFormBean f = (LoginFormBean) session.getAttribute( "loginHandler" );
//obtain a db connection and perform a db query
//ensuring that the username exists
// JCR 20040905 passing on portal home parameter
String portalIdStr=(portalIdStr=request.getParameter("home"))==null?String.valueOf(DEFAULT_PORTAL_ID):portalIdStr;
//request.setAttribute("home",portalIdStr);
// Build the redirect URLs
String contextPath = request.getContextPath();
String urlParams = "?home=" + portalIdStr + "&login=block";
String loginUrl = contextPath + Controllers.LOGIN + urlParams;
String siteAdminUrl = contextPath + Controllers.SITE_ADMIN + urlParams;
if (userDao==null) {
f.setErrorMsg("loginPassword","unable to get UserDao");
f.setLoginStatus("no UserDao");
response.sendRedirect(loginUrl);
return;
}
/* used for encoding cleartext passwords sent via http before store in database
String loginPassword = "";
String passwordQuery = "SELECT PASSWORD('" + f.getLoginPassword() + "')";
ResultSet ps = stmt.executeQuery( passwordQuery );
while ( ps.next() ) {
loginPassword = ps.getString(1);
}
*/
String userEnteredPasswordAfterMd5Conversion=f.getLoginPassword(); // won't be null
if ( userEnteredPasswordAfterMd5Conversion.equals("") ) { // shouldn't get through JS form verification
f.setErrorMsg( "loginPassword","please enter a password" );
f.setLoginStatus("bad_password");
response.sendRedirect(loginUrl);
return;
}
User user = userDao.getUserByUsername(f.getLoginName());
if (user==null) {
f.setErrorMsg( "loginName","No user found with username " + f.getLoginName() );
f.setLoginStatus("unknown_username");
response.sendRedirect(loginUrl);
return;
}
// logic for authentication
// first check for new users (loginCount==0)
// 1) cold (have username but haven't received initial password)
// 2) initial password has been set but user mis-typed it
// 3) correctly typed initial password and oldpassword set to provided password; have to enter a different one
// 4) entered same password again
// 5) entered a new private password, and bypass this stage because logincount set to 1
// then check for users DBA has set to require changing password (md5password is null, oldpassword is not)
//
// check password; dbMd5Password is md5password from database
if (user.getLoginCount() == 0 ) { // new user
if ( user.getMd5password() == null ) { // user is known but has not been given initial password
f.setErrorMsg( "loginPassword", "Please request a username and initial password via the link below" ); // store password in database but force immediate re-entry
f.setLoginStatus("first_login_no_password");
} else if (!user.getMd5password().equals( userEnteredPasswordAfterMd5Conversion )) { // mis-typed CCRP-provided initial password
if ( user.getOldPassword() == null ) { // did not make it through match of initially supplied password
f.setErrorMsg( "loginPassword", "Please try entering provided password again" );
f.setLoginStatus("first_login_mistyped");
} else if (user.getOldPassword().equals( userEnteredPasswordAfterMd5Conversion ) ) {
f.setErrorMsg( "loginPassword", "Please pick a different password from initially provided one" );
f.setLoginStatus("changing_password_repeated_old");
} else { // successfully provided different, private password
f.setErrorMsg( "loginPassword", "Please re-enter new private password" );
user.setMd5password(userEnteredPasswordAfterMd5Conversion);
user.setLoginCount(1);
userDao.updateUser(user);
f.setLoginStatus("changing_password");
}
} else { // entered a password that matches initial md5password in database; now force them to change it
// oldpassword could be null or not null depending on number of mistries
f.setErrorMsg( "loginPassword", "Please now choose a private password" ); // store password in database but force immediate re-entry
user.setOldPassword(user.getMd5password());
userDao.updateUser(user);
f.setLoginStatus("first_login_changing_password");
}
response.sendRedirect(loginUrl);
return;
} else if ( user.getMd5password()==null ) { // DBA has forced entry of a new password for user with a loginCount > 0
if ( user.getOldPassword() != null && user.getOldPassword().equals( userEnteredPasswordAfterMd5Conversion ) ) {
f.setErrorMsg( "loginPassword", "Please pick a different password from your old one" );
f.setLoginStatus("changing_password_repeated_old");
} else {
f.setErrorMsg( "loginPassword", "Please re-enter new password" );
user.setMd5password(userEnteredPasswordAfterMd5Conversion);
userDao.updateUser(user);
f.setLoginStatus("changing_password");
}
response.sendRedirect(loginUrl);
return;
} else if (!user.getMd5password().equals( userEnteredPasswordAfterMd5Conversion )) {
/*
* yxl: comment out the following code so that Shib can login an admin user
* without using a password as long as the glid existed in the "user" table.
*/
/*
f.setErrorMsg( "loginPassword", "Incorrect password: try again");
f.setLoginStatus("bad_password");
f.setLoginPassword(""); // don't even reveal how many characters there were
response.sendRedirect(loginUrl);
return;
*/
}
//set the login bean properties from the database
//System.out.println("authenticated; setting login status in loginformbean");
f.setUserURI(user.getURI());
f.setLoginStatus( "authenticated" );
f.setSessionId( session.getId());
f.setLoginRole( user.getRoleURI() );
try {
int loginRoleInt = Integer.decode(f.getLoginRole());
if( (loginRoleInt>1) && (session.isNew()) ) {
session.setMaxInactiveInterval(32000); // set longer timeout for editors
}
} catch (Exception e) {}
// TODO : might be a problem in next line - no ID
f.setLoginUserId( -2 );
//f.setEmailAddress ( email );
f.setLoginPassword( "" );
f.setErrorMsg( "loginPassword", "" ); // remove any error messages
f.setErrorMsg( "loginUsername", "" );
//System.out.println("updating loginCount and modTime");
Map<String,HttpSession> userURISessionMap = getUserURISessionMapFromContext( getServletContext() );
userURISessionMap.put( user.getURI(), request.getSession() );
sendLoginNotifyEvent(new LoginEvent( user.getURI() ), getServletContext(), session);
user.setLoginCount(user.getLoginCount()+1);
userDao.updateUser(user);
if ( user.getLoginCount() == 2 ) { // first login
Calendar cal = Calendar.getInstance();
user.setFirstTime(cal.getTime());
userDao.updateUser(user);
}
/*
*If you set a postLoginRequest attribute in the session and forward to about
*then this will attempt to send the client back to the original page after the login.
*/
String forwardStr = (String) request.getSession().getAttribute("postLoginRequest");
request.getSession().removeAttribute("postLoginRequest");
if (forwardStr == null) {
String contextPostLoginRequest = (String) getServletContext().getAttribute("postLoginRequest");
if (contextPostLoginRequest != null) {
forwardStr = (contextPostLoginRequest.indexOf(":") == -1)
? request.getContextPath() + contextPostLoginRequest
: contextPostLoginRequest;
}
}
if (forwardStr != null) {
response.sendRedirect(forwardStr);
} else {
response.sendRedirect(siteAdminUrl);
//RequestDispatcher rd = getServletContext().getRequestDispatcher(url);
//rd.forward(request,response);
}
} catch (Throwable t) {
log.error( t.getMessage() );
t.printStackTrace();
}
}
public static void sendLoginNotifyEvent(LoginLogoutEvent event, ServletContext context, HttpSession session){
Object sessionOntModel = null;
if( session != null )
sessionOntModel = session.getAttribute("jenaOntModel");
Object contextOntModel = null;
if( context != null )
contextOntModel = context.getAttribute("jenaOntModel");
OntModel jenaOntModel =
( (sessionOntModel != null && sessionOntModel instanceof OntModel)
? (OntModel)sessionOntModel: (OntModel) context.getAttribute("jenaOntModel") );
if( jenaOntModel == null ){
log.error( "Unable to notify audit model of login event because no model could be found");
} else {
if( event == null ){
log.warn("Unable to notify audit model of login because a null event was passed");
}else{
jenaOntModel.getBaseModel().notifyEvent( event );
}
}
}
public static Map<String,HttpSession> getUserURISessionMapFromContext( ServletContext ctx ) {
Map<String,HttpSession> m = (Map<String,HttpSession>) ctx.getAttribute( USER_SESSION_MAP_ATTR );
if ( m == null ) {
m = new HashMap<String,HttpSession>();
ctx.setAttribute( USER_SESSION_MAP_ATTR, m );
}
return m;
}
}