...
No Format |
---|
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>sakai-sample-tools-login</display-name> <description>Sakai 2 sample tools: login</description> <filter> <filter-name>sakai.request</filter-name> <filter-class>org.sakaiproject.util.RequestFilter</filter-class> </filter> <filter> <filter-name>sakai.request.container</filter-name> <filter-class>org.sakaiproject.util.RequestFilter</filter-class> <init-param> <param-name>tool.placement</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>remote.user</param-name> <param-value>false</param-value> </init-param> </filter> <!-- added for distauth --> <filter> <filter-name>ucdfilter</filter-name> <filter-class>edu.ucdavis.security.distauth.AuthenticationFilter</filter-class> <init-param> <param-name>LoginURL</param-name> <param-value></param-value> </init-param> <init-param> <param-name>InvalidCookieURL</param-name> <param-value></param-value> </init-param> <init-param> <param-name>InvalidLoginURL</param-name> <param-value></param-value> </init-param> <init-param> <param-name>InvalidTokenURL</param-name> <param-value></param-value> </init-param> <init-param> <param-name>InternalErrorURL</param-name> <param-value>Error.html</param-value> </init-param> <init-param> <param-name>TimeoutInterval</param-name> <param-value>3600</param-value> </init-param> <init-param> <param-name>TokenPath</param-name> <param-value>/afs/ucdavis.edu/common/authinfo/</param-value> </init-param> <init-param> <param-name>LogPath</param-name> <param-value></param-value> </init-param> <init-param> <param-name>LogFile</param-name> <param-value>C:\value>/var/tmp/distauth.log</param-value> </init-param> <init-param> <param-name>ValidateUserAgainstDB</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>DatabaseQuery</param-name> <param-value></param-value> </init-param> <init-param> <param-name>ProtectionLevel</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>PassThrough</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>LogoutURL</param-name> <param-value>https://secureweb.ucdavis.edu:443/form-auth/logout?</param-value> </init-param> <init-param> <param-name>SendBackURL</param-name> <param-value>https://secureweb.ucdavis.edu:443/form-auth/sendback?</param-value> </init-param> </filter> <filter-mapping> <filter-name>sakai.request</filter-name> <servlet-name>sakai.login</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <filter-mapping> <filter-name>sakai.request.container</filter-name> <servlet-name>sakai.login.container</servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping> <servlet> <servlet-name>sakai.login</servlet-name> <servlet-class>org.sakaiproject.tool.login.LoginTool</servlet-class> <init-param> <param-name>container</param-name> <param-value>/sakai-login/container</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>sakai.login.container</servlet-name> <servlet-class>org.sakaiproject.tool.login.ContainerLogin</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- map the container login, and then cause it to trigger container authentication --> <servlet-mapping> <servlet-name>sakai.login.container</servlet-name> <url-pattern>/container/*</url-pattern> </servlet-mapping> <!-- Turn distauth off/on --> <filter-mapping> <filter-name>ucdfilter</filter-name> <servlet-name>sakai.login.container</servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping> <listener> <listener-class>org.sakaiproject.util.ToolListener</listener-class> </listener> <!-- to add a user to this BASIC auth tomcat container authentication, add lines to your tomcat/conf/tomcat-users.xml: *** Enable this only if using Tomcat's built-in BASIC auth <tomcat-users> <role rolename="sakaiuser"/> <user username="NAME" password="PW" roles="sakaiuser"/> </tomcat-users> among the other definitions there --> <!-- Define a Security Constraint on this Application *** Enable this only if using Tomcat's built-in BASIC auth <security-constraint> <web-resource-collection> <web-resource-name>container</web-resource-name> <url-pattern>/container/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>sakaiuser</role-name> </auth-constraint> </security-constraint> *** --> <!-- Define the Login Configuration for this Application *** Enable this only if using Tomcat's built-in BASIC auth <login-config> <auth-method>BASIC</auth-method> <realm-name>Sakai Users</realm-name> </login-config> *** --> <!-- Security roles referenced by this web application *** Enable this only if using Tomcat's built-in BASIC auth <security-role> <description> The role that is required to log in to Sakai </description> <role-name>sakaiuser</role-name> </security-role> *** --> </web-app> |
- Enable Kerberos Provider, for WebDav support
- Request a krb5.keytab file for the server you are running (service ticket)
- Request a krb5.conf file for the server you are running
- Create a new file with the following contents. Name the file jaas.config.
No Format KerberosAuthentication { com.sun.security.auth.module.Krb5LoginModule required debug=false storekey=false clearPass=false useTicketCache=false useKeyTab=true keyTab="/etc/krb.keytab"; };
- Copy the above 3 files into your jdk-src/jre/lib/security/ directory. Note, in the jaas.config file you can identify where your keytab file resides if one wants to put it somewhere else. Also note the quotes around the file path.
- Enable the Kerberos Provider by first commenting out the SampleUserDirectoryProvider in the sakai-src/providers/src/component/src/webapp/WEB-INF/components.xml file. See below for the snippet to uncomment (REMEMBER TO COMMENT OUT THE SAMPLEUSERDIRECTORYPROVIDER!!!!):
No Format <!-- below is orinally commented out, see KerberosDirectoryProvider documentation for further info --> <bean id="org.sakaiproject.service.legacy.user.UserDirectoryProvider" class="org.sakaiproject.component.kerberos.user.KerberosUserDirectoryProvider" init-method="init" destroy-method="destroy" singleton="true"> <property name="logger"><ref bean="org.sakaiproject.service.framework.log.Logger"/></property> <property name="domain"><value>ucdavis.edu</value></property> <property name="loginContext"><value>KerberosAuthentication</value></property> <property name="requireLocalAccount"><value>true</value></property> <property name="knownUserMsg"><value>Integrity check on decrypted field failed</value></property> </bean>
- Uncomment the KerberosProvider in the sakai-src/providers/component/project.xml file. See below:
No Format <!-- Needed for the Kerberos Provider, is commented by default --> <dependency> <groupId>sakaiproject</groupId> <artifactId>sakai-kerberos-provider</artifactId> <version>${sakai.version}</version> <properties> <war.bundle>true</war.bundle> </properties> </dependency>
- Rebuild sakai for changes to take effect
- Enable logout functionality of Secureweb in Sakai
- Copy the contents of the following LoginTool.java code into the [saka-src/login/login/src/java/org/sakaiproject/tool/login directory. This file will replace the default code shipped with Sakai. Changes were made to the "complete" method to enable logout properly via DistAuth. Below is the entire code, or it may be found in SVN @ https://mware.ucdavis.edu/svn/sakai/distauth/trunk/LogoutSecureWebFunctionality/LoginTool.java
No Format /********************************************************************************** * * $Header: /cvs/sakai2/login/login/src/java/org/sakaiproject/tool/login/LoginTool.java,v 1.17 2005/06/04 03:14:22 ggolden.umich.edu Exp $ * *********************************************************************************** * * Copyright (c) 2005 The Regents of the University of Michigan, Trustees of Indiana University, * Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation * * Licensed under the Educational Community License Version 1.0 (the "License"); * By obtaining, using and/or copying this Original Work, you agree that you have read, * understand, and will comply with the terms and conditions of the Educational Community License. * You may obtain a copy of the License at: * * http://cvs.sakaiproject.org/licenses/license_1_0.html * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **********************************************************************************/ 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, 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/html; 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_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)); } } } /************************************************************************************************************************************************************************************************************************************************************** * $Header: /cvs/sakai2/login/login/src/java/org/sakaiproject/tool/login/LoginTool.java,v 1.17 2005/06/04 03:14:22 ggolden.umich.edu Exp $ *************************************************************************************************************************************************************************************************************************************************************/
- Rebuild Sakai
- Copy the contents of the following LoginTool.java code into the [saka-src/login/login/src/java/org/sakaiproject/tool/login directory. This file will replace the default code shipped with Sakai. Changes were made to the "complete" method to enable logout properly via DistAuth. Below is the entire code, or it may be found in SVN @ https://mware.ucdavis.edu/svn/sakai/distauth/trunk/LogoutSecureWebFunctionality/LoginTool.java
...