nicolaken 02/03/05 03:02:31 Added: src/scratchpad/src/org/apache/cocoon/acting DbXMLAuthenticatorAction.java Log: Added action to authenticate users with DBXML, contributed by Christian Zoffoli <[EMAIL PROTECTED]>. Revision Changes Path 1.1 xml-cocoon2/src/scratchpad/src/org/apache/cocoon/acting/DbXMLAuthenticatorAction.java Index: DbXMLAuthenticatorAction.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache Cocoon" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR * ITS 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.cocoon.acting; import org.apache.avalon.excalibur.datasource.DataSourceComponent; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.thread.ThreadSafe; import org.apache.cocoon.Constants; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Session; import org.apache.cocoon.environment.SourceResolver; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.xmldb.api.base.*; import org.xmldb.api.modules.*; import org.xmldb.api.*; import org.w3c.dom.*; import org.apache.xpath.*; import org.apache.xpath.objects.*; /** * This action is used to authenticate user by comparing several request * fields (username, password) with the values in a DBXML compliant database. * The description of the process is given via external xml description file * simiar to the one used for all actions derived from AbstractDatabaseAction. * * <pre> * <root> * * <connection> * <driver>org.apache.xindice.client.xmldb.DatabaseImpl</driver> * <base>xmldb:xindice:///db/beta</base> * </connection> * * <root name="users> * <select element="username" request-param="username" to-session="username"/> * <select element="password" request-param="password" nullable="yes"/> * * <select element="role" to-session="role" type="string"/> * <select element="skin" to-session="skin" type="string"/> * </root> * * </root> * </pre> * * The values specified via "request-param" describe the name of HTTP request * parameter, "element" indicates matching document node, "nullable" means * that request-param which is null or empty will not be included in the WHERE * clause. This way you can enable accounts with empty passwords, etc. * "to-session" attribute indicates under which name the value obtained from * database should be stored in the session. Of course new session is created * when authorization is successfull. The "type" attribute can be either * string, long or double and alters the type of object stored in session. * Additionally all parameters that are * propagated to the session are made available to the sitemap via {name} * expression. * * If there is no need to touch the session object, providing just one-time * verification, you can specify action parameter "create-session" to "no" or * "false". No values are then propagated to the sesion and session object is * not verified. * * @author <a href="mailto:[EMAIL PROTECTED]">Christian Zoffoli</a> * @author <a href="mailto:[EMAIL PROTECTED]">Martin Man</a> * @version 0.2 -- 2002/02/03 * * based on DatabaseAuthenticatorAction created by Martin Man <[EMAIL PROTECTED]> */ public class DbXMLAuthenticatorAction extends AbstractDatabaseAction implements ThreadSafe { /** * Main invocation routine. */ public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws Exception { ResourceSet rs = null; // read global parameter settings boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT; if (this.settings.containsKey("reloadable")) { reloadable = Boolean.getBoolean((String) this.settings.get("reloadable")); } // read local settings try { Configuration conf = this.getConfiguration ( parameters.getParameter ("descriptor", (String) this.settings.get("descriptor")), resolver, parameters.getParameterAsBoolean("reloadable", reloadable)); boolean cs = true; String create_session = parameters.getParameter ("create-session", (String) this.settings.get("create-session")); if (create_session != null && ("no".equals (create_session.trim ()) || "false".equals (create_session.trim ()))) { cs = false; } Request req = (Request) objectModel.get(Constants.REQUEST_OBJECT); /* check request validity */ if (req == null) { getLogger ().debug ("DBXMLAUTH: no request object"); return null; } rs = this.Authenticate( conf, req ); if (rs != null ) { getLogger ().debug ("DBXMLAUTH: authorized successfully"); Session session = null; if (cs) { session = req.getSession (false); if (session != null) session.invalidate (); session = req.getSession (true); if (session == null) return null; getLogger ().debug ("DBXMLAUTH: session created"); } else { getLogger ().debug ("DBXMLAUTH: leaving session untouched"); } HashMap actionMap = this.propagateParameters (conf, rs, session); return Collections.unmodifiableMap (actionMap); } else { //getLogger ().debug ("DBXMLAUTH: error ResourceSet is null"); } req.setAttribute("message", "The username or password were incorrect, please check your CAPS LOCK key and try again."); getLogger ().debug ("DBXMLAUTH: no results for query"); } catch (Exception e) { getLogger().debug ("exception: ", e); return null; } return null; } private String getAuthQuery ( Configuration conf, Request req ) { boolean first_constraint = true; StringBuffer queryBuffer = new StringBuffer ("//"); StringBuffer queryBufferEnd = new StringBuffer (""); String dbcol, request_param, request_value, nullstr; boolean nullable = false; Configuration table = conf.getChild ("root"); Configuration[] select = table.getChildren ("select"); try { queryBuffer.append (table.getAttribute ("name")); for (int i = 0; i < select.length; i ++) { dbcol = "[" + select[i].getAttribute ("element"); try { request_param = select[i].getAttribute ("request-param"); if (request_param == null || request_param.trim().equals ("")) { continue; } } catch (Exception e) { continue; } try { nullstr = select[i].getAttribute ("nullable"); if (nullstr != null) nullstr = nullstr.trim (); if ("yes".equals (nullstr) || "true".equals (nullstr)) { nullable = true; } } catch (Exception e1) { } /* if there is a request parameter name, * but not the value, we exit immediately do * that authorization fails authomatically */ request_value = req.getParameter (request_param); if (request_value == null || request_value.trim().equals ("")) { // value is null if (!nullable) { getLogger ().debug ("DBXMLAUTH: request-param " + request_param + " does not exist"); return null; } } else { queryBufferEnd.append (dbcol).append("='").append(request_value).append("']"); first_constraint = false; } } if (!queryBufferEnd.toString ().trim ().equals ("")) queryBuffer.append (queryBufferEnd); return queryBuffer.toString (); } catch (Exception e) { getLogger ().debug ("DBXMLAUTH: got exception: " + e); return null; } } private ResourceSet Authenticate( Configuration conf, Request req) throws Exception, XMLDBException { ResourceSet rs = null; String query = this.getAuthQuery (conf, req); if (query == null) { getLogger ().debug ("DBXMLAUTH: have not got query"); req.setAttribute("message", "The authenticator is misconfigured"); return null; } getLogger ().debug ("DBXMLAUTH: query is: " + query); Collection col = CreateConnection( conf ); if ( col != null ) { if ( col.isOpen() ) { try { XPathQueryService service = (XPathQueryService) col.getService("XPathQueryService", "1.0"); rs = service.query(query); ResourceIterator results = rs.getIterator(); if (results.hasMoreResources() == false) { getLogger ().debug ("DBXMLAUTH: auth failed"); return null; } else { getLogger ().debug ("DBXMLAUTH: auth OK"); return rs; } } catch (XMLDBException e) { getLogger ().debug ("DBXMLAUTH: got exception: " + e); return null; } finally { // close col if (col != null) { try { col.close(); } catch (Exception e) { /* ignore */ } } getLogger ().debug ("DBXMLAUTH: collection closed"); } } else { getLogger ().debug ("DBXMLAUTH: error: collection closed !!"); } } else { getLogger ().debug ("DBXMLAUTH: couldn't open a connection with DB"); } return null; } private Collection CreateConnection( Configuration conf ) throws Exception, XMLDBException { Collection col = null; Configuration conn = conf.getChild ("connection"); try { Class c = Class.forName( conn.getChild("driver").getValue() ); Database database = (Database) c.newInstance(); DatabaseManager.registerDatabase(database); col = DatabaseManager.getCollection( conn.getChild("base").getValue() ); } catch (XMLDBException e) { getLogger ().debug ("DBXMLAUTH: Exception occured " + e.errorCode); } return col; } private HashMap propagateParameters (Configuration conf, ResourceSet resultSet, Session session) { Configuration table = conf.getChild ("root"); Configuration[] select = table.getChildren ("select"); String dbcol, session_param, type; HashMap map = new HashMap(); XObject xo; Node originalnode = null; try { ResourceIterator results = resultSet.getIterator(); // Create an XObject to be used in Xpath query xo = new XObject(); // Retrieve the next node XMLResource resource = (XMLResource) results.nextResource(); originalnode = resource.getContentAsDOM(); } catch (Exception e) { getLogger ().debug ("DBXMLAUTH: error creating XObject "); } try { for (int i = 0; i < select.length; i ++) { dbcol = select[i].getAttribute ("element"); try { session_param = select[i].getAttribute ("to-session"); if (session_param != null && !session_param.trim().equals ("")) { String s = ""; try { // Use Xalan xpath parser to extract data xo = XPathAPI.eval(originalnode, "/" + table.getAttribute ("name") + "/" + select[i].getAttribute ("element") ); s = xo.toString(); } catch (Exception e) { } /* propagate to session */ try { type = select[i].getAttribute ("type"); } catch (Exception e) { type = null; } if (type == null || "".equals (type.trim ())) { type = "string"; } Object o = null; if ("string".equals (type)) { o = s; } else if ("long".equals (type)) { Long l = Long.decode (s); o = l; } else if ("double".equals (type)) { Double d = Double.valueOf (s); o = d; } if (session != null) { session.setAttribute (session_param, o); getLogger ().debug ("DBXMLAUTH: propagating param " + session_param + "=" + s); } map.put (session_param, o); } } catch (Exception e) { } } return map; } catch (Exception e) { getLogger().debug("exception: ", e); } return null; } }
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]