Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

#1. modify the complete() method signature, and appropriate calls to be include the reply string. See following:

Code Block

package org.sakaiproject.tool.login;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.api.common.authentication.Authentication;
import org.sakaiproject.api.common.authentication.AuthenticationException;
import org.sakaiproject.api.common.authentication.Evidence;
import org.sakaiproject.api.common.authentication.cover.AuthenticationManager;
import org.sakaiproject.api.kernel.session.Session;
import org.sakaiproject.api.kernel.session.cover.SessionManager;
import org.sakaiproject.api.kernel.tool.Tool;
import org.sakaiproject.service.framework.config.cover.ServerConfigurationService;
import org.sakaiproject.util.IdPwEvidence;
import org.sakaiproject.util.LoginUtil;
import org.sakaiproject.util.web.Web;

/**
 * <p>
 * Login tool for Sakai. Works with the ContainerLoginTool servlet to offer container or internal login.
 * </p>
 * <p>
 * This "tool", being login, is not placed, instead each user can interact with only one login at a time. The Sakai Session is used for attributes.
 * </p>
 * 
 * @author University of Michigan, Sakai Software Development Team
 * @version $Revision: 666 $
 */
public class LoginTool extends HttpServlet
{
	/** Our log (commons). */
	private static Log M_log = LogFactory.getLog(LoginTool.class);

	/** Session attribute used to store a message between steps. */
	protected static final String ATTR_MSG = "sakai.login.message";

	/** Session attribute set and shared with ContainerLoginTool: URL for redirecting back here. */
	public static final String ATTR_RETURN_URL = "sakai.login.return.url";

	/** Session attribute set and shared with ContainerLoginTool: if set we have failed container and need to check internal. */
	public static final String ATTR_CONTAINER_CHECKED = "sakai.login.container.checked";

	/**
	 * Access the Servlet's information display.
	 * 
	 * @return servlet information.
	 */
	public String getServletInfo()
	{
		return "Sakai Login";
	}

	/**
	 * Initialize the servlet.
	 * 
	 * @param config
	 *        The servlet config.
	 * @throws ServletException
	 */
	public void init(ServletConfig config) throws ServletException
	{
		super.init(config);

		M_log.info("init()");
	}

	/**
	 * Shutdown the servlet.
	 */
	public void destroy()
	{
		M_log.info("destroy()");

		super.destroy();
	}

	/**
	 * Respond to requests.
	 * 
	 * @param req
	 *        The servlet request.
	 * @param res
	 *        The servlet response.
	 * @throws ServletException.
	 * @throws IOException.
	 */
	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		// get the session
		Session session = SessionManager.getCurrentSession();

		// get my tool registration
		Tool tool = (Tool) req.getAttribute(Tool.TOOL);

		// recognize what to do from the path
		String option = req.getPathInfo();
		System.out.println(option + "=this logout option*****************");
		// maybe we don't want to do the container this time
		boolean skipContainer = false;

		// if missing, set it to "/login"
		if ((option == null) || ("/".equals(option)))
		{
			option = "/login";
		}
		
		// look for the extreme login (i.e. to skip container checks)
		else if ("/xlogin".equals(option))
		{
			option = "/login";
			skipContainer = true;
		}

		// get the parts (the first will be "", second will be "login" or "logout")
		String[] parts = option.split("/");

		if (parts[1].equals("logout"))
		{
			// get the session info complete needs, since the logout will invalidate and clear the session
			String returnUrl = (String) session.getAttribute(Tool.HELPER_DONE_URL);

			// logout the user
			LoginUtil.logout();

			complete(returnUrl, Session session, Tool tool, HttpServletResponse res, String reply null, tool, res,"logout");
			return;
		}
		else
		{
			// see if we need to check container
			boolean checkContainer = ServerConfigurationService.getBoolean("container.login", false);
			if (checkContainer && !skipContainer)
			{
				// if we have not checked the container yet, check it now
				if (session.getAttribute(ATTR_CONTAINER_CHECKED) == null)
				{
					// save our return path
					session.setAttribute(ATTR_RETURN_URL, Web.returnUrl(req, null));

					String containerCheckPath = this.getServletConfig().getInitParameter("container");
					String containerCheckUrl = Web.serverUrl(req) + containerCheckPath;

					res.sendRedirect(res.encodeRedirectURL(containerCheckUrl));
					return;
				}
			}

			// send the form
			sendForm(req, res);
		}
	}

	/**
	 * Send the login form
	 * 
	 * @param req
	 *        Servlet request.
	 * @param res
	 *        Servlet response.
	 * @throws IOException
	 */
	protected void sendForm(HttpServletRequest req, HttpServletResponse res) throws IOException
	{
		final String headHtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
				+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">"
				+ "  <head>"
				+ "    <meta http-equiv=\"Content-Type\" content=\"text//added info by Scott Amerson to include logout url for secureweb
				
		
		// cleanup session
		if (session != null)
		{
			session.removeAttribute(Tool.HELPER_MESSAGE);
			session.removeAttribute(Tool.HELPER_DONE_URL);
			session.removeAttribute(ATTR_MSGhtml; charset=UTF-8\" />"
				+ "    <link href=\"SKIN_ROOT/tool_base.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />"
				+ "    <link href=\"SKIN_ROOT/DEFAULT_SKIN/tool.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />"
				+ "    <meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />"
				+ "    <title>Sakai</title>"
				+ "    <script type=\"text/javascript\" language=\"JavaScript\" src=\"/library/js/headscripts.js\"></script>"
				+ "  </head>"
				+ "  <body onload=\" setFocus(focus_path);parent.updCourier(doubleDeep, ignoreCourier);\">"
				+ "<script type=\"text/javascript\" language=\"JavaScript\">" + "  focus_path = [\"eid\"];" + "</script>";

		final String tailHtml = "</body></html>";

		final String loginHtml = "<table border=\"3\" cellpadding=\"0\" cellspacing=\"0\" width=\"470\" style =\"margin-right:auto;margin-left:auto;margin-top:5em;background-color:#fff;font-family:helvetica,arial,sans-serif\">"
				+ "	<tr>"
				+ "		<td>"
				+ "			<table bgcolor=\"#FFFFFF\" border=\"0\" cellpadding=\"5\" cellspacing=\"0\">"
				+ "				<tr>"
				+ "					<td colspan=\"2\" bgcolor=\"#11375E\" align=\"left\">"
				+ "						<b style=\"color:#ffffff; font-size: 12pt\">"
				+ "							Login Required"
				+ "						</b>"
				+ "					</td>"
				+ "				</tr>"
				+ "				<tr>"
				+ "					<td>"
				+ "						<img src=\"SKIN_ROOT/DEFAULT_SKIN/images/logo_inst.gif\" border=\"0\" hspace=\"0\" vspace=\"0\" alt=\"\" />"
				+ "					</td>"
				+ "					<td valign=\"top\">"
				+ "						<form method=\"post\" action=\"ACTION\" enctype=\"application/x-www-form-urlencoded\">"
				+ "							<table border=\"0\">"
				+ "								<tr>"
				+ "									<td style=\"font-weight:bold;\">"
				+ "										EID"
				+ "									</td>"
				+ "									<td>"
				+ "										<input name=\"eid\" id=\"eid\"  type=\"text\" style =\"width: 10em\" />"
				+ "									</td>"
				+ "								</tr>"
				+ "								<tr>"
				+ "									<td style=\"font-weight:bold;\">"
				+ "										PW"
				+ "									</td>"
				+ "									<td>"
				+ "										<input name=\"pw\" type=\"password\" style =\"width: 10em\" />"
				+ "									</td>"
				+ "								</tr>"
				+ "								<tr>"
				+ "									<td colspan=\"2\" align=\"right\">"
				+ "										<input name=\"submit\" type=\"submit\" id=\"submit\" value=\"Log in\" style=\"float:right\" />"
				+ "                                        MSG"
				+ "									</td>"
				+ "								</tr>"
				+ "							</table>"
				+ "						</form>"
				+ "					</td>"
				+ "				</tr>"
				+ "			</table>" + "		</td>" + "	</tr>" + "</table>";

		// get the Sakai session
		Session session = SessionManager.getCurrentSession();

		// get my tool registration
		Tool tool = (Tool) req.getAttribute(Tool.TOOL);

		// fragment or not?
		boolean fragment = Boolean.TRUE.toString().equals(req.getAttribute(Tool.FRAGMENT));

		String eidWording = null;
		String pwWording = null;

		// read my configuration
		if (tool != null)
		{
			eidWording = tool.getRegisteredConfig().getProperty("eid");
			pwWording = tool.getRegisteredConfig().getProperty("pw");
		}

		if (eidWording == null) eidWording = "eid";
		if (pwWording == null) pwWording = "pw";

		if (!fragment)
		{
			// set our response type
			res.setContentType("text/html; charset=UTF-8");
		}

		String defaultSkin = ServerConfigurationService.getString("skin.default");
		String skinRoot = ServerConfigurationService.getString("skin.repo");

		// get our response writer
		PrintWriter out = res.getWriter();

		if (!fragment)
		{
			// start our complete document
			String head = headHtml.replaceAll("DEFAULT_SKIN", defaultSkin);
			head = head.replaceAll("SKIN_ROOT", skinRoot);
			out.println(head);
		}

		// if we are in helper mode, there might be a helper message
		if (session.getAttribute(Tool.HELPER_MESSAGE) != null)
		{
			out.println("<p>" + session.getAttribute(Tool.HELPER_MESSAGE) + "</p>");
		}

		// add our return URL
		String returnUrl = res.encodeURL(Web.returnUrl(req, null));
		String html = loginHtml.replaceAll("ACTION", res.encodeURL(returnUrl));

		// add our wording
		html = html.replaceAll("EID", eidWording);
		html = html.replaceAll("PW", pwWording);

		// add the default skin
		html = html.replaceAll("DEFAULT_SKIN", defaultSkin);
		html = html.replaceAll("SKIN_ROOT", skinRoot);

		// write a message if present
		String msg = (String) session.getAttribute(ATTR_MSG);
		if (msg != null)
		{
			html = html.replaceAll("MSG", "<div class=\"chefAlertBox\">Alert: " + msg + "</div>");
			session.removeAttribute(ATTR_RETURN_URL);
			session.removeAttribute(ATTR_CONTAINER_CHECKED);
		}

		// redirect to the done URL
		//only send user to secureweb on /logout path, not /xlogin or /login
                MSG);
		}
		else
		{
			html = html.replaceAll("MSG", "");
		}

		// write the login screen
		out.println(html);

		if (!fragment)
		{
			// close the complete document
			out.println(tailHtml);
		}
	}

	/**
	 * Respond to data posting requests.
	 * 
	 * @param req
	 *        The servlet request.
	 * @param res
	 *        The servlet response.
	 * @throws ServletException.
	 * @throws IOException.
	 */
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
	{
		// get the Sakai session
		Session session = SessionManager.getCurrentSession();

		// get my tool registration
		Tool tool = (Tool) req.getAttribute(Tool.TOOL);

		// here comes the data back from the form... these fields will be present, blank if not filled in
		String eid = req.getParameter("eid").trim();
		String pw = req.getParameter("pw").trim();

		// one of these will be there, one null, depending on how the submit was done
		String submit = req.getParameter("submit");
		String cancel = req.getParameter("cancel");

		// cancel
		if (cancel != null)
		{
			session.setAttribute(ATTR_MSG, "login canceled");

			// get the session info complete needs, since the logout will invalidate and clear the session
			String returnUrl = (String) session.getAttribute(Tool.HELPER_DONE_URL);

			// TODO: send to the cancel URL, cleanup session
			complete(returnUrl, session, tool, res,"cancel");
		}

		// submit
		else
		{
			Evidence e = new IdPwEvidence(eid, pw);

			// authenticate
			try
			{
				if ((eid.length() == 0) || (pw.length() == 0))
				{
					throw new AuthenticationException("missing required fields");
				}

				Authentication a = AuthenticationManager.authenticate(e);

				// login the user
				LoginUtil.login(a, req);

				// get the session info complete needs, since the logout will invalidate and clear the session
				String returnUrl = (String) session.getAttribute(Tool.HELPER_DONE_URL);
				
				complete(returnUrl, session, tool, res,"auth");
			}
			catch (AuthenticationException ex)
			{
				session.setAttribute(ATTR_MSG, "invalid login");

				// respond with a redirect back here
				res.sendRedirect(res.encodeRedirectURL(Web.returnUrl(req, null)));
			}
		}
	}


	/**
	 * Cleanup and redirect when we have a successful login / logout
	 * 
	 * @param session
	 * @param tool
	 * @param res
	 * @throws IOException
	 */
	
	protected void complete(String returnUrl, Session session, Tool tool, HttpServletResponse res, String reply) throws IOException
	{
		//added info by Scott Amerson to include logout url for secureweb
				
		
		// cleanup session
		if (session != null)
		{
			session.removeAttribute(Tool.HELPER_MESSAGE);
			session.removeAttribute(Tool.HELPER_DONE_URL);
			session.removeAttribute(ATTR_MSG);
			session.removeAttribute(ATTR_RETURN_URL);
			session.removeAttribute(ATTR_CONTAINER_CHECKED);
		}

		// redirect to the done URL
		if (reply.equals("logout"))
		{
		String LogOutURL = ServerConfigurationService.getString("secureweb.logoutURL", "");
		res.sendRedirect(LogOutURL + res.encodeRedirectURL(returnUrl));	
		}
		else
		{	
		res.sendRedirect(res.encodeRedirectURL(returnUrl));
		}
	}

	

}


#2. Add the following secureweb logout url value to the Tomcat/sakai/sakai.properties file:

...