Java tutorial
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed 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.apache.cocoon.acting; 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.ObjectModelHelper; 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 org.apache.commons.lang.BooleanUtils; import org.apache.xpath.XPathAPI; import org.apache.xpath.objects.XObject; import org.w3c.dom.Node; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Collection; import org.xmldb.api.base.Database; import org.xmldb.api.base.ResourceIterator; import org.xmldb.api.base.ResourceSet; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.XMLResource; import org.xmldb.api.modules.XPathQueryService; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 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> * @since 2002/02/03 * @version $Id: DbXMLAuthenticatorAction.java 369504 2006-01-16 16:11:12Z jbq $ * * based on DatabaseAuthenticatorAction created by Martin Man <Martin.Man@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.valueOf((String) this.settings.get("reloadable")).booleanValue(); } // 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 = ObjectModelHelper.getRequest(objectModel); /* 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) { 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 (BooleanUtils.toBoolean(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("']"); } } 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 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 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++) { 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; } }