Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » acting » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.cocoon.acting;
   18   
   19   import org.apache.avalon.excalibur.datasource.DataSourceComponent;
   20   import org.apache.avalon.framework.configuration.Configuration;
   21   import org.apache.avalon.framework.parameters.Parameters;
   22   import org.apache.avalon.framework.thread.ThreadSafe;
   23   import org.apache.cocoon.Constants;
   24   import org.apache.cocoon.environment.ObjectModelHelper;
   25   import org.apache.cocoon.environment.Redirector;
   26   import org.apache.cocoon.environment.Request;
   27   import org.apache.cocoon.environment.Session;
   28   import org.apache.cocoon.environment.SourceResolver;
   29   import org.apache.commons.lang.BooleanUtils;
   30   import org.apache.commons.lang.StringUtils;
   31   
   32   import java.sql.Connection;
   33   import java.sql.ResultSet;
   34   import java.sql.PreparedStatement;
   35   import java.util.Collections;
   36   import java.util.HashMap;
   37   import java.util.Map;
   38   
   39   /**
   40    * This action is used to authenticate user by comparing several request
   41    * fields (username, password) with the values in database. The description of
   42    * the process is given via external xml description file simiar to the one
   43    * used for all actions derived from AbstractDatabaseAction.
   44    * <pre>
   45    * &lt;root&gt;
   46    *         &lt;connection&gt;personnel&lt;/connection&gt;
   47    *         &lt;table name="users_table&gt;
   48    *                 &lt;select dbcol="username" request-param="username"
   49    *                 to-session="username"/&gt;
   50    *                 &lt;select dbcol="password" request-param="password"
   51    *                 nullable="yes"/&gt;
   52    *                 &lt;select dbcol="role" to-session="role" type="string"/&gt;
   53    *                 &lt;select dbcol="skin" to-session="skin" type="string"/&gt;
   54    *         &lt;/table&gt;
   55    * &lt;/root&gt;
   56    * </pre>
   57    * The values specified via "request-param" describe the name of HTTP request
   58    * parameter, "dbcol" indicates matching database column, "nullable" means
   59    * that request-param which is null or empty will not be included in the WHERE
   60    * clause. This way you can enable accounts with empty passwords, etc.
   61    * "to-session" attribute indicates under which name the value obtained from
   62    * database should be stored in the session. Of course new session is created
   63    * when authorization is successfull. The "type" attribute can be either
   64    * string, long or double and alters the type of object stored in session.
   65    * Additionally all parameters that are
   66    * propagated to the session are made available to the sitemap via {name}
   67    * expression.
   68    *
   69    * If there is no need to touch the session object, providing just one-time
   70    * verification, you can specify action parameter "create-session" to "no" or
   71    * "false". No values are then propagated to the sesion and session object is
   72    * not verified.
   73    *
   74    * @author <a href="mailto:Martin.Man@seznam.cz">Martin Man</a>
   75    * @version CVS $Id: DatabaseAuthenticatorAction.java 433543 2006-08-22 06:22:54Z crossley $
   76    */
   77   public class DatabaseAuthenticatorAction extends AbstractDatabaseAction implements ThreadSafe
   78   {
   79       /**
   80        * Main invocation routine.
   81        */
   82       public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String src,
   83               Parameters parameters) throws Exception {
   84           DataSourceComponent datasource = null;
   85           Connection conn = null;
   86           PreparedStatement st = null;
   87           ResultSet rs = null;
   88   
   89           // read global parameter settings
   90           boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT;
   91   
   92           if (this.settings.containsKey("reloadable")) {
   93               reloadable = Boolean.valueOf((String) this.settings.get("reloadable")).booleanValue();
   94           }
   95   
   96           // read local settings
   97           try {
   98               Configuration conf = this.getConfiguration (
   99                       parameters.getParameter ("descriptor", (String) this.settings.get("descriptor")),
  100               resolver,
  101               parameters.getParameterAsBoolean("reloadable",reloadable));
  102               boolean cs = true;
  103               String create_session = parameters.getParameter ("create-session",
  104                                    (String) this.settings.get("create-session"));
  105               if (create_session != null) {
  106                   cs = BooleanUtils.toBoolean(create_session.trim());
  107                }
  108   
  109               datasource = this.getDataSource(conf);
  110               conn = datasource.getConnection();
  111               Request req = ObjectModelHelper.getRequest(objectModel);
  112   
  113               /* check request validity */
  114               if (req == null) {
  115                   getLogger ().debug ("DBAUTH: no request object");
  116                   return null;
  117               }
  118   
  119               st = this.getAuthQuery (conn, conf, req);
  120               if (st == null) {
  121                   getLogger ().debug ("DBAUTH: have not got query");
  122                   req.setAttribute("message", "The authenticator is misconfigured");
  123                   return null;
  124               }
  125   
  126               rs = st.executeQuery ();
  127   
  128               if (rs.next ()) {
  129                   getLogger ().debug ("DBAUTH: authorized successfully");
  130                   Session session = null;
  131   
  132                   if (cs) {
  133                       session = req.getSession (false);
  134                       if (session != null)
  135                           session.invalidate ();
  136                       session = req.getSession (true);
  137                       if (session == null)
  138                           return null;
  139                       getLogger ().debug ("DBAUTH: session created");
  140                   } else {
  141                       getLogger ().debug ("DBAUTH: leaving session untouched");
  142                   }
  143   
  144                   HashMap actionMap = this.propagateParameters (conf, rs,
  145                           session);
  146                   if(!conn.getAutoCommit()) {
  147                       conn.commit();
  148                   }
  149                   return Collections.unmodifiableMap (actionMap);
  150               }
  151               if(!conn.getAutoCommit()) {
  152                   conn.rollback();
  153               }
  154   
  155               req.setAttribute("message", "The username or password were incorrect, please check your CAPS LOCK key and try again.");
  156               getLogger ().debug ("DBAUTH: no results for query");
  157           } catch (Exception e) {
  158               if (conn != null) {
  159                   try {
  160                       if(!conn.getAutoCommit()) {
  161                           conn.rollback();
  162                       }
  163                   } catch (Exception se) {/* ignore */}
  164               }
  165               getLogger().debug ("exception: ", e);
  166               return null;
  167           } finally {
  168               if (rs != null) rs.close();
  169               if (st != null) st.close();
  170               if (conn != null) {
  171                   try {
  172                       conn.close();
  173                   } catch (Exception e) {/* ignore */}
  174               }
  175           }
  176           return null;
  177       }
  178   
  179       private PreparedStatement getAuthQuery(Connection conn, Configuration conf, Request req) {
  180           StringBuffer queryBuffer = new StringBuffer("SELECT ");
  181           StringBuffer queryBufferEnd = new StringBuffer("");
  182           Configuration table = conf.getChild("table");
  183           Configuration[] columns = table.getChildren("select");
  184           try {
  185               Object[] constraintValues = new Object[columns.length];
  186               int constraints = 0;
  187               for (int i = 0; i < columns.length; i++) {
  188                   String dbcol = columns[i].getAttribute("dbcol");
  189                   boolean nullable = false;
  190                   if (i > 0) {
  191                       queryBuffer.append (", ");
  192                   }
  193                   queryBuffer.append(dbcol);
  194   
  195                   String requestParameter = columns[i].getAttribute("request-param", null);
  196                   if (StringUtils.isNotBlank(requestParameter)) {
  197                       String nullstr = columns[i].getAttribute("nullable", null);
  198                       if (nullstr != null) {
  199                           nullable = BooleanUtils.toBoolean(nullstr.trim());
  200                       }
  201                       String constraintValue = req.getParameter(requestParameter);
  202   
  203                       // if there is a request parameter name,
  204                       // but not the value, we exit immediately do
  205                       // that authorization fails authomatically
  206                       if (StringUtils.isBlank(constraintValue) && !nullable) {
  207                           getLogger().debug("DBAUTH: request-param " + requestParameter + " does not exist");
  208                           return null;
  209                       }
  210                       if (constraints > 0) {
  211                           queryBufferEnd.append(" AND ");
  212                       }
  213                       queryBufferEnd.append(dbcol).append("= ?");
  214                       constraintValues[constraints++] = constraintValue;
  215                   }
  216               }
  217   
  218               queryBuffer.append(" FROM ");
  219               queryBuffer.append(table.getAttribute("name"));
  220               if (StringUtils.isNotBlank(queryBufferEnd.toString())) {
  221                   queryBuffer.append(" WHERE ").append(queryBufferEnd);
  222               }
  223   
  224               getLogger().debug("DBAUTH: query " + queryBuffer);
  225   
  226               PreparedStatement st = conn.prepareStatement(queryBuffer.toString());
  227   
  228               for (int i = 0; i < constraints; i++) {
  229                   getLogger().debug("DBAUTH: parameter " + (i+1) + " = [" + String.valueOf(constraintValues[i]) + "]");
  230                   st.setObject(i+1,constraintValues[i]);
  231               }
  232               return st;
  233           }
  234           catch (Exception e) {
  235               getLogger().debug("DBAUTH: got exception: " + e);
  236           }
  237           return null;
  238       }
  239   
  240       private HashMap propagateParameters (Configuration conf, ResultSet rs,
  241               Session session) {
  242           Configuration table = conf.getChild ("table");
  243           Configuration[] select = table.getChildren ("select");
  244           String session_param, type;
  245           HashMap map = new HashMap();
  246           try {
  247               for (int i = 0; i < select.length; i ++) {
  248                   try {
  249                       session_param = select[i].getAttribute ("to-session");
  250                       if (StringUtils.isNotBlank(session_param)) {
  251                           Object o = null;
  252                           String s = rs.getString (i + 1);
  253                           /* propagate to session */
  254                               type = select[i].getAttribute("type", "");
  255                           if (StringUtils.isBlank(type) || "string".equals (type)) {
  256                               o = s;
  257                           } else if ("long".equals (type)) {
  258                               Long l = Long.decode (s);
  259                               o = l;
  260                           } else if ("double".equals (type)) {
  261                               Double d = Double.valueOf (s);
  262                               o = d;
  263                           }
  264                           if (session != null) {
  265                               session.setAttribute (session_param, o);
  266                               getLogger ().debug ("DBAUTH: propagating param "
  267                                       + session_param + "=" + s);
  268                           }
  269                           map.put (session_param, o);
  270                       }
  271                   } catch (Exception e) {
  272                       // Empty
  273                   }
  274               }
  275               return map;
  276           } catch (Exception e) {
  277               getLogger().debug("exception: ", e);
  278           }
  279           return null;
  280       }
  281   }

Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » acting » [javadoc | source]