Author: jleroux
Date: Fri Sep 12 01:24:10 2008 New Revision: 694647 URL: http://svn.apache.org/viewvc?rev=694647&view=rev Log: A modified patch from Shi Yusen "CASifying OFBiz" (https://issues.apache.org/jira/browse/OFBIZ-1689) - OFBIZ-1689 This add LDAP functionnalities to OFBiz. Following discussion in dev ML I kept it in specialpurpose/ldap Need more work for Windows Active Directory Added: ofbiz/trunk/specialpurpose/ldap/ (with props) ofbiz/trunk/specialpurpose/ldap/build.xml (with props) ofbiz/trunk/specialpurpose/ldap/config/ ofbiz/trunk/specialpurpose/ldap/config/ldap.xml (with props) ofbiz/trunk/specialpurpose/ldap/lib/ ofbiz/trunk/specialpurpose/ldap/lib/cas-server-core-3.1.jar (with props) ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml (with props) ofbiz/trunk/specialpurpose/ldap/src/ ofbiz/trunk/specialpurpose/ldap/src/org/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java (with props) ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java (with props) ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java (with props) ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java (with props) ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java (with props) ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java (with props) Modified: ofbiz/trunk/LICENSE ofbiz/trunk/NOTICE ofbiz/trunk/specialpurpose/build.xml Modified: ofbiz/trunk/LICENSE URL: http://svn.apache.org/viewvc/ofbiz/trunk/LICENSE?rev=694647&r1=694646&r2=694647&view=diff ============================================================================== --- ofbiz/trunk/LICENSE (original) +++ ofbiz/trunk/LICENSE Fri Sep 12 01:24:10 2008 @@ -2532,3 +2532,35 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ==================================================================================== + +==================================================================================== +The following libraries distributed with Apache OFBiz are licensed under the +JA-SIG License +ofbiz/trunk/specialpurpose/ldap/lib/cas-server-core-3.1.jar +========================================================================= +Copyright (c) 2007, JA-SIG, Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the JA-SIG, Inc. nor the names of its contributors may be used to endorse + or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Modified: ofbiz/trunk/NOTICE URL: http://svn.apache.org/viewvc/ofbiz/trunk/NOTICE?rev=694647&r1=694646&r2=694647&view=diff ============================================================================== --- ofbiz/trunk/NOTICE (original) +++ ofbiz/trunk/NOTICE Fri Sep 12 01:24:10 2008 @@ -361,7 +361,7 @@ Extensions API) * Other classes such as HttpClient and various related ones use the JSSE (Java Secure Sockets Extension) API -================================================================ +======================================================================== == JPIM Notice == ======================================================================== This product includes software developed by jpim development team ( @@ -370,4 +370,12 @@ jpim is released under a modified BSD style license. Java PIM Library (jpim) -Copyright (c) 2001-2003 jpim development team. \ No newline at end of file +Copyright (c) 2001-2003 jpim development team. + +========================================================================= +== CAS Notice == +========================================================================= + +This product includes software developed by the +Java Architectures (JA-SIG) association (http://www.ja-sig.org/). + Modified: ofbiz/trunk/specialpurpose/build.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/build.xml?rev=694647&r1=694646&r2=694647&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/build.xml (original) +++ ofbiz/trunk/specialpurpose/build.xml Fri Sep 12 01:24:10 2008 @@ -28,7 +28,8 @@ oagis/build.xml, googlebase/build.xml, ebay/build.xml, - projectmgr/build.xml"/> + projectmgr/build.xml, + ldap/build.xml"/> <!-- For the old OFBiz Workflow Engine add "workflow/build.xml" to the list above --> <!-- For Shark add "shark/build.xml" to the list above, in the specialpurpose-builds list (after workflow) --> Propchange: ofbiz/trunk/specialpurpose/ldap/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Fri Sep 12 01:24:10 2008 @@ -0,0 +1 @@ +build Added: ofbiz/trunk/specialpurpose/ldap/build.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/build.xml?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/build.xml (added) +++ ofbiz/trunk/specialpurpose/ldap/build.xml Fri Sep 12 01:24:10 2008 @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<project name="OFBiz - LDAP Component" default="jar" basedir="."> + + <!-- ================================================================== --> + <!-- Initialization of all property settings --> + <!-- ================================================================== --> + + <target name="init"> + <property environment="env"/> + <property name="desc" value="LDAP Component"/> + <property name="name" value="ofbiz-ldap"/> + <property name="ofbiz.home.dir" value="../.."/> + <property name="src.dir" value="src"/> + <property name="dtd.dir" value="dtd"/> + <property name="lib.dir" value="lib"/> + <property name="build.dir" value="build"/> + </target> + + <target name="classpath"> + <path id="local.class.path"> + <fileset dir="${lib.dir}" includes="*.jar"/> + <fileset dir="../../framework/base/lib" includes="*.jar"/> + <fileset dir="../../framework/base/lib/commons" includes="*.jar"/> + <fileset dir="../../framework/base/lib/j2eespecs" includes="*.jar"/> + <fileset dir="../../framework/base/build/lib" includes="*.jar"/> + <fileset dir="../../framework/entity/lib" includes="*.jar"/> + <fileset dir="../../framework/entity/build/lib" includes="*.jar"/> + <fileset dir="../../framework/security/build/lib" includes="*.jar"/> + <fileset dir="../../framework/service/lib" includes="*.jar"/> + <fileset dir="../../framework/service/build/lib" includes="*.jar"/> + <fileset dir="../../framework/minilang/build/lib" includes="*.jar"/> + <fileset dir="../../framework/widget/build/lib" includes="*.jar"/> + <fileset dir="../../framework/webapp/lib" includes="*.jar"/> + <fileset dir="../../framework/webapp/build/lib" includes="*.jar"/> + <fileset dir="../../framework/common/build/lib" includes="*.jar"/> + </path> + </target> + + <!-- ================================================================== --> + <!-- Removes all created files and directories --> + <!-- ================================================================== --> + + <target name="clean" depends="clean-lib"> + <delete dir="${build.dir}"/> + </target> + + <target name="clean-lib" depends="init"> + <delete dir="${build.dir}/lib"/> + </target> + + <!-- ================================================================== --> + <!-- Makes sure the needed directory structure is in place --> + <!-- ================================================================== --> + + <target name="prepare" depends="clean-lib"> + <mkdir dir="${build.dir}/classes"/> + <mkdir dir="${build.dir}/lib"/> + </target> + + <target name="prepare-docs" depends="init"> + <mkdir dir="${build.dir}/javadocs"/> + </target> + + <!-- ================================================================== --> + <!-- Compilation of the source files --> + <!-- ================================================================== --> + + <target name="classes" depends="prepare,classpath"> + <javac debug="on" source="1.5" deprecation="on" destdir="${build.dir}/classes"> + <classpath> + <path refid="local.class.path"/> + </classpath> + <src path="${src.dir}"/> + </javac> + <copy todir="${build.dir}/classes"> + <!-- don't put the DTDs in the jar file... --> + <fileset dir="${src.dir}" includes="**/*.properties,**/*.xml,**/*.bsh,**/*.logic,**/*.js,**/*.jacl,**/*.py"/> + </copy> + + <!-- now add the NOTICE and LICENSE files to allow the jar file to be distributed alone --> + <copy todir="${build.dir}/classes/META-INF"> + <fileset dir="${ofbiz.home.dir}" includes="NOTICE,LICENSE"/> + </copy> + </target> + + <target name="jar" depends="classes"> + <jar jarfile="${build.dir}/lib/${name}.jar" basedir="${build.dir}/classes"/> + </target> + + <!-- ================================================================== --> + <!-- Build JavaDoc --> + <!-- ================================================================== --> + + <target name="docs" depends="prepare-docs,classpath"> + <javadoc packagenames="org.ofbiz.*" + classpathref="local.class.path" + destdir="${build.dir}/javadocs" + Windowtitle="Open for Business - ${desc}"> + <sourcepath path="${src.dir}"/> + </javadoc> + </target> + + <target name="all" depends="jar,docs"/> + +</project> Propchange: ofbiz/trunk/specialpurpose/ldap/build.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/build.xml ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/build.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/ldap/config/ldap.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/config/ldap.xml?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/config/ldap.xml (added) +++ ofbiz/trunk/specialpurpose/ldap/config/ldap.xml Fri Sep 12 01:24:10 2008 @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<ldap> + <!-- common configuration --> + <Attribute>uid=%u</Attribute> + <AuthenType>simple</AuthenType> + <AuthenticationHandler>org.ofbiz.ldap.cas.OFBizCasAuthenticationHandler</AuthenticationHandler> + <AutoPartyId>admin</AutoPartyId> + <AutoSecurityGroupId>FULLADMIN</AutoSecurityGroupId> + <BaseDN>o=ofbiz,o=org</BaseDN> + <Filter>(objectclass=*)</Filter> + <Scope>sub</Scope> + <URL>ldap://localhost:389</URL> + <UseOFBizLoginWhenLDAPFail>true</UseOFBizLoginWhenLDAPFail> + + <!-- for CAS-LDAP --> + <CasLoginUri>/login</CasLoginUri> + <CasLogoutUri>/logout</CasLogoutUri> + <CasUrl>https://localhost:8443/cas</CasUrl> + <CasValidateUri>/validate</CasValidateUri> + <CasLdapHandler>org.ofbiz.ldap.openldap.OFBizLdapAuthenticationHandler</CasLdapHandler> + <CasTGTCookieName>CASTGC</CasTGTCookieName> + + <!-- for MS Active Directory --> + <SearchType/> + <UserDNForSearch/> + <PasswordForSearch/> +</ldap> Propchange: ofbiz/trunk/specialpurpose/ldap/config/ldap.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/config/ldap.xml ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/config/ldap.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/ldap/lib/cas-server-core-3.1.jar URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/lib/cas-server-core-3.1.jar?rev=694647&view=auto ============================================================================== Binary file - no diff available. Propchange: ofbiz/trunk/specialpurpose/ldap/lib/cas-server-core-3.1.jar ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml (added) +++ ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml Fri Sep 12 01:24:10 2008 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +<ofbiz-component name="ldap" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/ofbiz-component.xsd"> + <!-- define resource loaders; most common is to use the component resource loader --> + <resource-loader name="main" type="component"/> + + <!-- place the config directory on the classpath to access configuration files --> + <classpath type="dir" location="config"/> + + <!-- load single or multiple external libraries --> + <classpath type="jar" location="build/lib/*"/> + <classpath type="jar" location="lib/*"/> + +</ofbiz-component> Propchange: ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/ofbiz-component.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,264 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.ldap; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.*; + +import javax.naming.NamingException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; + +import org.ofbiz.base.util.*; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.ldap.commons.InterfaceOFBizAuthenticationHandler; +import org.ofbiz.webapp.control.LoginWorker; +import org.ofbiz.webapp.control.RequestHandler; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * Common LDAP Login Workers + */ +public class LdapLoginWorker extends LoginWorker { + + private static final String ldapConfig = "specialpurpose/ldap/config/ldap.xml"; + + /** + * An HTTP WebEvent handler that checks to see is a userLogin is logged in. + * If not, the user is forwarded to the login page. + * + * @param request The HTTP request object for the current JSP or Servlet request. + * @param response The HTTP response object for the current JSP or Servlet request. + * @return String + */ + public static String checkLogin(HttpServletRequest request, HttpServletResponse response) { + GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin"); + // anonymous shoppers are not logged in + if (userLogin != null && "anonymous".equals(userLogin.getString("userLoginId"))) { + userLogin = null; + } + + // user is logged in; check to see if they have globally logged out if not + // check if they have permission for this login attempt; if not log them out + if (userLogin != null) { + Element rootElement = getRootElement(request); + boolean hasLdapLoggedOut = false; + if (rootElement != null) { + String className = UtilXml.childElementValue(rootElement, "AuthenticationHandler", "org.ofbiz.ldap.openldap.OFBizLdapAuthenticationHandler"); + try { + Class<?> handlerClass = Class.forName(className); + InterfaceOFBizAuthenticationHandler authenticationHandler = (InterfaceOFBizAuthenticationHandler) handlerClass.newInstance(); + hasLdapLoggedOut = authenticationHandler.hasLdapLoggedOut(request, response, rootElement); + } catch (ClassNotFoundException e) { + Debug.logError(e, "Error calling checkLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (InstantiationException e) { + Debug.logError(e, "Error calling checkLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (IllegalAccessException e) { + Debug.logError(e, "Error calling checkLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (Exception e) { + Debug.logError(e, "Error calling checkLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } + } + + if (!hasBasePermission(userLogin, request) || isFlaggedLoggedOut(userLogin) || hasLdapLoggedOut) { + Debug.logInfo("User does not have permission or is flagged as logged out", module); + doBasicLogout(userLogin, request); + userLogin = null; + } + } + + if (userLogin == null) { + return login(request, response); + } + + return "success"; + } + + /** + * An HTTP WebEvent handler that logs in a userLogin. This should run before the security check. + * + * @param request The HTTP request object for the current JSP or Servlet request. + * @param response The HTTP response object for the current JSP or Servlet request. + * @return Return a boolean which specifies whether or not the calling Servlet or + * JSP should generate its own content. This allows an event to override the default content. + */ + public static String login(HttpServletRequest request, HttpServletResponse response) { + + Element rootElement = getRootElement(request); + String result = "error"; + if (rootElement != null) { + String className = UtilXml.childElementValue(rootElement, "AuthenticationHandler", "org.ofbiz.ldap.openldap.OFBizLdapAuthenticationHandler"); + try { + Class<?> handlerClass = Class.forName(className); + InterfaceOFBizAuthenticationHandler authenticationHandler = (InterfaceOFBizAuthenticationHandler) handlerClass.newInstance(); + result = authenticationHandler.login(request, response, rootElement); + } catch (ClassNotFoundException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (InstantiationException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (IllegalAccessException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (NamingException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (Exception e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } + } + + if (result.equals("error")) { + boolean useOFBizLoginWhenFail = Boolean.getBoolean(UtilXml.childElementValue(rootElement, "UseOFBizLoginWhenLDAPFail", "false")); + if (useOFBizLoginWhenFail) { + return LoginWorker.login(request, response); + } + } + return result; + } + + /** + * An HTTP WebEvent handler that logs out a userLogin by clearing the session. + * + * @param request The HTTP request object for the current request. + * @param response The HTTP response object for the current request. + * @return Return a boolean which specifies whether or not the calling request + * should generate its own content. This allows an event to override the default content. + */ + public static String logout(HttpServletRequest request, HttpServletResponse response) { + // run the before-logout events + RequestHandler rh = RequestHandler.getRequestHandler(request.getSession().getServletContext()); + rh.runBeforeLogoutEvents(request, response); + + // invalidate the security group list cache + GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin"); + + doBasicLogout(userLogin, request); + + Element rootElement = getRootElement(request); + + String result = "error"; + if (rootElement != null) { + String className = UtilXml.childElementValue(rootElement, "AuthenticationHandler", "org.ofbiz.ldap.openldap.OFBizLdapAuthenticationHandler"); + try { + Class<?> handlerClass = Class.forName(className); + InterfaceOFBizAuthenticationHandler authenticationHandler = (InterfaceOFBizAuthenticationHandler) handlerClass.newInstance(); + result = authenticationHandler.logout(request, response, rootElement); + } catch (ClassNotFoundException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (InstantiationException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (IllegalAccessException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (Exception e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } + } + + if (request.getAttribute("_AUTO_LOGIN_LOGOUT_") == null) { + return autoLoginCheck(request, response); + } + return result; + } + + protected static Element getRootElement(HttpServletRequest request) { + if (Debug.infoOn()) { + Debug.log("Applet config file: " + ldapConfig); + } + File configFile = new File(ldapConfig); + FileInputStream configFileIS = null; + Element rootElement = null; + try { + configFileIS = new FileInputStream(configFile); + Document configDoc = UtilXml.readXmlDocument(configFileIS, "LDAP configuration file " + ldapConfig); + rootElement = configDoc.getDocumentElement(); + } catch (FileNotFoundException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (SAXException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (ParserConfigurationException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } catch (IOException e) { + Debug.logError(e, "Error calling userLogin service", module); + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + String errMsg = UtilProperties.getMessage(resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } finally { + if (configFileIS != null) { + try { + configFileIS.close(); + } catch (IOException e) { + } + } + } + + return rootElement; + } +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/LdapLoginWorker.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,118 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.ldap.activedirectory; + +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import org.jasig.cas.util.LdapUtils; +import org.ofbiz.base.util.UtilXml; +import org.ofbiz.ldap.commons.AbstractOFBizAuthenticationHandler; +import org.w3c.dom.Element; + + +/** + * The OFBiz ActiveDirectory Authentication Handler.<p> + * + * The ACL of a user is still controlled by OFBiz. + * + */ +public final class OFBizActiveDirectoryAuthenticationHandler extends AbstractOFBizAuthenticationHandler { + + /** + * Public constructor, initializes some required member variables.<p> + */ + public OFBizActiveDirectoryAuthenticationHandler() { + + } + + public SearchResult getLdapSearchResult(String username, String password, + Element rootElement, boolean bindRequired) throws NamingException { + DirContext ctx = null; + SearchResult result = null; + String ldapURL = UtilXml.childElementValue(rootElement, "URL", "ldap://localhost:389"); + String authenType = UtilXml.childElementValue(rootElement, "AuthenType", "simple"); + String searchType = UtilXml.childElementValue(rootElement, "SearchType", ""); + String baseDN = UtilXml.childElementValue(rootElement, "BaseDN"); + Hashtable<String, String> env = new Hashtable<String, String>(); + env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, ldapURL); + if (searchType == null || searchType.trim().equals("")) { + env.put(Context.SECURITY_AUTHENTICATION, "none"); + } else if (searchType.trim().equals("login")) { + env.put(Context.SECURITY_AUTHENTICATION, authenType); + // specify the username for search + String userDNForSearch = UtilXml.childElementValue(rootElement, "UserDNForSearch"); + env.put(Context.SECURITY_PRINCIPAL, userDNForSearch); + // specify the password for search + String passwordForSearch = UtilXml.childElementValue(rootElement, "PasswordForSearch"); + env.put(Context.SECURITY_CREDENTIALS, passwordForSearch); + } + try { + ctx = new InitialDirContext(env); + SearchControls controls = new SearchControls(); + // ldap search timeout + controls.setTimeLimit(1000); + // ldap search count + controls.setCountLimit(2); + // ldap search scope + String sub = UtilXml.childElementValue(rootElement, "Scope", "sub").toLowerCase().trim(); + if (sub.equals("sub")) { + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + } else if (sub.equals("one")){ + controls.setSearchScope(SearchControls.ONELEVEL_SCOPE); + } else { + controls.setSearchScope(SearchControls.OBJECT_SCOPE); + } + String filter = UtilXml.childElementValue(rootElement, "Filter", "(objectclass=*)"); + String attribute = UtilXml.childElementValue(rootElement, "Attribute", "uid=%u"); + attribute = LdapUtils.getFilterWithValues(attribute, username); + NamingEnumeration<SearchResult> answer = ctx.search(baseDN, + // Filter expression + "(&(" + filter + ") (" + attribute +"))", + controls); + if (answer.hasMoreElements()) { + result = (SearchResult) answer.next(); + if (bindRequired) { + env.put(Context.SECURITY_AUTHENTICATION, authenType); + // specify the username + String userDN = result.getName() + "," + baseDN; + env.put(Context.SECURITY_PRINCIPAL, userDN); + // specify the password + env.put(Context.SECURITY_CREDENTIALS, password); + ctx = new InitialDirContext(env); + } + } + } catch (NamingException e) { + // No ldap service found, or cannot login. + throw new NamingException(e.getLocalizedMessage()); + } + + return result; + } + +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/activedirectory/OFBizActiveDirectoryAuthenticationHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,193 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.ldap.cas; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import javax.naming.NamingException; +import javax.naming.directory.SearchResult; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.ofbiz.base.util.UtilXml; +import org.ofbiz.ldap.commons.AbstractOFBizAuthenticationHandler; +import org.ofbiz.ldap.commons.InterfaceOFBizAuthenticationHandler; +import org.w3c.dom.Element; + +/** + * The OFBiz CAS-LDAP Authentication Handler.<p> + * + * The ACL of a user is still controlled by OFBiz. + * + */ +public final class OFBizCasAuthenticationHandler extends AbstractOFBizAuthenticationHandler { + + public static final String PARAM_TICKET = "ticket"; + + public static final String PARAM_SERVICE = "service"; + + public static final String PARAM_RENEW = "renew"; + + /** + * Public constructor, initializes some required member variables.<p> + */ + public OFBizCasAuthenticationHandler() { + + } + + + public String login(HttpServletRequest request, HttpServletResponse response, Element rootElement) throws Exception { + + String ticket = request.getParameter(PARAM_TICKET); + String username = request.getParameter("USERNAME"); + String password = request.getParameter("PASSWORD"); + + String casUrl = UtilXml.childElementValue(rootElement, "CasUrl", "https://localhost:8443/cas"); + String loginUri = UtilXml.childElementValue(rootElement, "CasLoginUri", "/login"); + String validateUri = UtilXml.childElementValue(rootElement, "CasValidateUri", "/validate"); + String serviceUrl = request.getRequestURL().toString(); + String url = URLEncoder.encode(serviceUrl, "UTF-8"); + boolean casLoggedIn = false; + if (ticket == null) { + // forward the login page to CAS login page + response.sendRedirect(casUrl + loginUri + "?" + PARAM_SERVICE + "=" + url); + } else { + // there's a ticket, we should validate the ticket + URL validateURL = new URL(casUrl + validateUri + "?" + PARAM_TICKET + "=" + ticket + "&" + PARAM_SERVICE + "=" + url); + URLConnection conn = validateURL.openConnection(); + InputStreamReader result = null; + BufferedReader reader = null; + try { + result = new InputStreamReader(conn.getInputStream(), "UTF-8"); + reader = new BufferedReader(result); + String oneline = reader.readLine(); + if (oneline != null && oneline.equals("yes")) { + // the ticket is true + username = reader.readLine().trim(); + casLoggedIn = true; + } else { + // the ticket is false, forward the request to cas login page + response.sendRedirect(casUrl + loginUri + "?service=" + url); + } + } catch (Exception e) { + if (reader != null) { + try { + reader.close(); + } catch (Exception e1) { + } + } + if (result != null) { + try { + result.close(); + } catch (Exception e1) { + } + } + } + } + + if (casLoggedIn && username != null) { + // as we cannot get the password user input in CAS login page, we use a random one + password = randomString(); + SearchResult result = getLdapSearchResult(username, password, rootElement, false); + if (result != null) { + return login(request, response, username, password, rootElement, result); + } + } + return "error"; + } + + public static String randomString(int lo, int hi){ + int n = rand(lo, hi); + byte b[] = new byte[n]; + for (int i = 0; i < n; i++) { + b[i] = (byte)rand('a', 'z'); + } + return new String(b); + } + + private static int rand(int lo, int hi){ + java.util.Random rn = new java.util.Random(); + int n = hi - lo + 1; + int i = rn.nextInt() % n; + if (i < 0) + i = -i; + return lo + i; + } + + public static String randomString(){ + return randomString(5, 15); + } + + public String logout(HttpServletRequest request, HttpServletResponse response, Element rootElement) { + String casUrl = UtilXml.childElementValue(rootElement, "CasUrl", "https://localhost:8443/cas"); + String logoutUri = UtilXml.childElementValue(rootElement, "CasLogoutUri", "/logout"); + try { + response.sendRedirect(casUrl + logoutUri); + } catch (UnsupportedEncodingException e) { + } catch (IOException e) { + } + return "success"; + } + + + public SearchResult getLdapSearchResult(String username, String password, + Element rootElement, boolean bindRequired) throws NamingException { + String className = UtilXml.childElementValue(rootElement, "CasLdapHandler", "org.ofbiz.ldap.openldap.OFBizLdapAuthenticationHandler"); + try { + Class<?> handlerClass = Class.forName(className); + InterfaceOFBizAuthenticationHandler casLdapHandler = (InterfaceOFBizAuthenticationHandler) handlerClass.newInstance(); + return casLdapHandler.getLdapSearchResult(username, password, rootElement, bindRequired); + } catch (ClassNotFoundException e) { + throw new NamingException(e.getLocalizedMessage()); + } catch (InstantiationException e) { + throw new NamingException(e.getLocalizedMessage()); + } catch (IllegalAccessException e) { + throw new NamingException(e.getLocalizedMessage()); + } + } + + /** + * An HTTP WebEvent handler that checks to see is a userLogin is logged out. + * If yes, the user is forwarded to the login page. + * + * @param request The HTTP request object for the current JSP or Servlet request. + * @param response The HTTP response object for the current JSP or Servlet request. + * @param rootElement Element root element of ldap config file + * @return true if the user has logged out from ldap; otherwise, false. + */ + public boolean hasLdapLoggedOut(HttpServletRequest request, HttpServletResponse response, Element rootElement) { + String casTGC = UtilXml.childElementValue(rootElement, "CasTGTCookieName", "CASTGC"); + String casUrl = UtilXml.childElementValue(rootElement, "CasUrl", "https://localhost:8443/cas"); + Cookie[] cookies = request.getCookies(); + if (cookies == null) return true; + for (int i=0; i < cookies.length; i++) { + Cookie cookie = cookies[i]; + if (cookie.getName().equals(casTGC) && casUrl.indexOf(cookie.getDomain()) > -1) { + return false; + } + } + return true; + } +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/cas/OFBizCasAuthenticationHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,156 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.ldap.commons; + +import static org.ofbiz.base.util.UtilGenerics.checkMap; + +import java.util.Map; + +import javax.naming.NamingException; +import javax.naming.directory.SearchResult; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.ofbiz.base.crypto.HashCrypt; +import org.ofbiz.base.util.UtilDateTime; +import org.ofbiz.base.util.UtilHttp; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilProperties; +import org.ofbiz.base.util.UtilXml; +import org.ofbiz.common.login.LoginServices; +import org.ofbiz.entity.GenericDelegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.ldap.LdapLoginWorker; +import org.ofbiz.service.GenericServiceException; +import org.ofbiz.service.LocalDispatcher; +import org.ofbiz.service.ModelService; +import org.ofbiz.webapp.stats.VisitHandler; +import org.w3c.dom.Element; + +/** + * The abstract Authentication Handler. + * + * The ACL of a user is still controlled by OFBiz.<p> + * + */ +public abstract class AbstractOFBizAuthenticationHandler implements InterfaceOFBizAuthenticationHandler { + + /** + * Public constructor, initializes some required member variables.<p> + */ + public AbstractOFBizAuthenticationHandler() { + + } + + public Object getPartyId(Element rootElement, SearchResult result) { + Object partyId = UtilXml.childElementValue(rootElement, "AutoPartyId", "admin"); + return partyId; + } + + public Object getSecurityGroup(Element rootElement, SearchResult result) { + Object securityGroupId = UtilXml.childElementValue(rootElement, "AutoSecurityGroupId", "FULLADMIN"); + return securityGroupId; + } + + public String login(HttpServletRequest request, HttpServletResponse response, Element rootElement) throws Exception { + + String username = request.getParameter("USERNAME"); + String password = request.getParameter("PASSWORD"); + + SearchResult result = getLdapSearchResult(username, password, rootElement, true); + if (result != null) { + return login(request, response, username, password, rootElement, result); + } + return "error"; + } + + public String logout(HttpServletRequest request, HttpServletResponse response, Element rootElement) { + return "success"; + } + + public abstract SearchResult getLdapSearchResult(String username, String password, Element rootElement, boolean bindRequired) throws NamingException; + + public String login(HttpServletRequest request, HttpServletResponse response, String username, String password, Element rootElement, SearchResult result) throws Exception { + HttpSession session = request.getSession(); + + // get the visit id to pass to the userLogin for history + String visitId = VisitHandler.getVisitId(session); + LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher"); + GenericDelegator delegator = dispatcher.getDelegator(); + boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt")); + GenericValue userLoginToCreate = delegator.makeValue("UserLogin", UtilMisc.toMap("userLoginId", username)); + userLoginToCreate.set("passwordHint", ""); + userLoginToCreate.set("enabled", "Y"); + userLoginToCreate.set("partyId", getPartyId(rootElement, result)); + userLoginToCreate.set("currentPassword", useEncryption ? HashCrypt.getDigestHash(password, LoginServices.getHashType()) : password); + + GenericValue userTryToLogin = delegator.findOne("UserLogin", false, "userLoginId", username); + if (userTryToLogin == null) { + // create the userLogin + try { + userLoginToCreate.create(); + } catch (GenericEntityException e) { + throw new GenericEntityException(e.getLocalizedMessage()); + } + + GenericValue userLoginSecurityGroup = delegator.makeValue("UserLoginSecurityGroup", UtilMisc.toMap("userLoginId", username, "groupId", getSecurityGroup(rootElement, result), "fromDate", UtilDateTime.nowTimestamp())); + try { + userLoginSecurityGroup.create(); + } catch (GenericEntityException e) { + throw new GenericEntityException(e.getLocalizedMessage()); + } + } else { + userTryToLogin.setString("currentPassword", useEncryption ? HashCrypt.getDigestHash(password, LoginServices.getHashType()) : password); + userTryToLogin.store(); + } + + Map<String, Object> loginResult = null; + + try { + loginResult = dispatcher.runSync("userLogin", UtilMisc.toMap("login.username", username, "login.password", password, "visitId", visitId, "locale", UtilHttp.getLocale(request))); + } catch (GenericServiceException e) { + throw new GenericServiceException(e.getLocalizedMessage()); + } + if (ModelService.RESPOND_SUCCESS.equals(loginResult.get(ModelService.RESPONSE_MESSAGE))) { + GenericValue userLogin = (GenericValue) loginResult.get("userLogin"); + Map<String, Object> userLoginSession = checkMap(loginResult.get("userLoginSession"), String.class, Object.class); + return LdapLoginWorker.doMainLogin(request, response, userLogin, userLoginSession); + } else { + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", (String) loginResult.get(ModelService.ERROR_MESSAGE)); + String errMsg = UtilProperties.getMessage(LdapLoginWorker.resourceWebapp, "loginevents.following_error_occurred_during_login", messageMap, UtilHttp.getLocale(request)); + throw new Exception(errMsg); + } + } + + /** + * An HTTP WebEvent handler that checks to see is a userLogin is logged out. + * If yes, the user is forwarded to the login page. + * + * @param request The HTTP request object for the current JSP or Servlet request. + * @param response The HTTP response object for the current JSP or Servlet request. + * @param rootElement Element root element of ldap config file + * @return true if the user has logged out from ldap; otherwise, false. + */ + public boolean hasLdapLoggedOut(HttpServletRequest request, HttpServletResponse response, Element rootElement) { + return false; + } +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/AbstractOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,103 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.ldap.commons; + +import javax.naming.NamingException; +import javax.naming.directory.SearchResult; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Element; + +/** + * The OFBiz LDAP Authentication Handler interface.<p> + * + */ +public interface InterfaceOFBizAuthenticationHandler { + + /** + * Login a user. + * + * @param request HttpServletRequest + * @param response HttpServletResponse + * @param rootElement Element root element of ldap config file + * + * @return success if the user can login successfully; otherwise, error. + * @throws Exception + */ + String login(HttpServletRequest request, HttpServletResponse response, Element rootElement) throws Exception; + + /** + * Get the security group of a user. + * + * @param rootElement Element root element of ldap config file + * @param result SearchResult + * + * @return the SecurityGroup object. + */ + Object getSecurityGroup(Element rootElement, SearchResult result); + + /** + * Get the party id of a user. + * + * @param rootElement Element root element of ldap config file + * @param result SearchResult + * + * @return the PartyId object. + */ + Object getPartyId(Element rootElement, SearchResult result); + + /** + * Logout a user. + * + * @param request HttpServletRequest + * @param response HttpServletResponse + * @param rootElement Element root element of ldap config file + * + * @return success if the user can login successfully; otherwise, error. + * @throws Exception + */ + String logout(HttpServletRequest request, HttpServletResponse response, Element rootElement); + + /** + * Get LDAP search result from a username, password and configuration. + * + * @param username String + * @param password String + * @param rootElement Element root element of ldap config file + * @param bindRequired boolean if true, bind; false, just search the user in LDAP + * + * @return result SearchResult if ldap search successfully; otherwise, null. + * @throws Exception + */ + SearchResult getLdapSearchResult(String username, String password, Element rootElement, boolean bindRequired) throws NamingException; + + /** + * An HTTP WebEvent handler that checks to see is a userLogin is logged out in ldap. + * If yes, the user is forwarded to the login page. + * Currently, this function is only used in CAS authentication handler. + * + * @param request The HTTP request object for the current JSP or Servlet request. + * @param response The HTTP response object for the current JSP or Servlet request. + * @param rootElement Element root element of ldap config file + * @return true if the user has logged out from ldap; otherwise, false. + */ + boolean hasLdapLoggedOut(HttpServletRequest request, HttpServletResponse response, Element rootElement); +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/commons/InterfaceOFBizAuthenticationHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java?rev=694647&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java (added) +++ ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java Fri Sep 12 01:24:10 2008 @@ -0,0 +1,103 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ + +package org.ofbiz.ldap.openldap; + +import java.util.Hashtable; +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import org.jasig.cas.util.LdapUtils; +import org.ofbiz.base.util.UtilXml; +import org.ofbiz.ldap.commons.AbstractOFBizAuthenticationHandler; +import org.w3c.dom.Element; + +/** + * The OFBiz LDAP Authentication Handler.<p> + * + * The ACL of a user is still controlled by OFBiz. + * + */ +public final class OFBizLdapAuthenticationHandler extends AbstractOFBizAuthenticationHandler { + + /** + * Public constructor, initializes some required member variables.<p> + */ + public OFBizLdapAuthenticationHandler() { + + } + + public SearchResult getLdapSearchResult(String username, String password, Element rootElement, boolean bindRequired) throws NamingException { + DirContext ctx = null; + SearchResult result = null; + String ldapURL = UtilXml.childElementValue(rootElement, "URL", "ldap://localhost:389"); + String authenType = UtilXml.childElementValue(rootElement, "AuthenType", "simple"); + String baseDN = UtilXml.childElementValue(rootElement, "BaseDN"); + Hashtable<String, String> env = new Hashtable<String, String>(); + env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, ldapURL); + env.put(Context.SECURITY_AUTHENTICATION, "none"); + try { + ctx = new InitialDirContext(env); + SearchControls controls = new SearchControls(); + // ldap search timeout + controls.setTimeLimit(1000); //TODO maybe properties... + // ldap search count + controls.setCountLimit(2); //TODO maybe properties... + // ldap search scope + String sub = UtilXml.childElementValue(rootElement, "Scope", "sub").toLowerCase().trim(); + if (sub.equals("sub")) { + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + } else if (sub.equals("one")){ + controls.setSearchScope(SearchControls.ONELEVEL_SCOPE); + } else { + controls.setSearchScope(SearchControls.OBJECT_SCOPE); + } + String filter = UtilXml.childElementValue(rootElement, "Filter", "(objectclass=*)"); + String attribute = UtilXml.childElementValue(rootElement, "Attribute", "uid=%u"); + attribute = LdapUtils.getFilterWithValues(attribute, username); + NamingEnumeration<SearchResult> answer = ctx.search(baseDN, + // Filter expression + "(&(" + filter + ") (" + attribute +"))", + controls); + if (answer.hasMoreElements()) { + result = (SearchResult) answer.next(); + if (bindRequired) { + env.put(Context.SECURITY_AUTHENTICATION, authenType); + // specify the username + String userDN = result.getName() + "," + baseDN; + env.put(Context.SECURITY_PRINCIPAL, userDN); + // specify the password + env.put(Context.SECURITY_CREDENTIALS, password); + ctx = new InitialDirContext(env); + } + } + } catch (NamingException e) { + // No ldap service found, or cannot login. + throw new NamingException(e.getLocalizedMessage()); + } + + return result; + } + +} Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/specialpurpose/ldap/src/org/ofbiz/ldap/openldap/OFBizLdapAuthenticationHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain |
Free forum by Nabble | Edit this page |