You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by ni...@apache.org on 2002/03/05 12:02:31 UTC

cvs commit: xml-cocoon2/src/scratchpad/src/org/apache/cocoon/acting DbXMLAuthenticatorAction.java

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 <cz...@littlepenguin.org>.
  
  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 apache@apache.org.
   *
   * 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:czoffoli@littlepenguin.org">Christian Zoffoli</a>
   * @author <a href="mailto:Martin.Man@seznam.cz">Martin Man</a>
   * @version 0.2 -- 2002/02/03
   *
   * based on DatabaseAuthenticatorAction created by Martin Man <Ma...@seznam.cz>
   */
  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:     webmaster@xml.apache.org
To unsubscribe, e-mail:          cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org