| /* |
| * 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.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.Cookie; |
| 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.commons.lang.StringUtils; |
| |
| import java.sql.Connection; |
| import java.sql.ResultSet; |
| import java.sql.Statement; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * This action is used to authenticate user by comparing several cookie values |
| * (username, password) with the values in 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>personnel</connection> |
| * <table name="users_table> |
| * <select dbcol="username" cookie-name="username" |
| * to-session="username"/> |
| * <select dbcol="password" cookie-name="password" |
| * nullable="yes"/> |
| * <select dbcol="role" to-session="role" type="string"/> |
| * <select dbcol="skin" to-session="skin" type="string"/> |
| * </table> |
| * </root> |
| * </pre> The values specified via "cookie-name" describe the name of the |
| * cookie, "dbcol" indicates matching database column, "nullable" means that |
| * cookie-name 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. If you want to append |
| * attributes to the session without creating a new one, specify action |
| * parameter "append-session" to "yes" or "true". |
| * |
| * @author <a href="mailto:paolo@arsenio.net">Paolo Scaffardi</a> |
| * @version CVS $Id$ |
| */ |
| public class DatabaseCookieAuthenticatorAction extends AbstractDatabaseAction implements ThreadSafe { |
| |
| /** |
| * Main invocation routine. |
| * |
| * @param redirector Description of Parameter |
| * @param resolver Description of Parameter |
| * @param objectModel Description of Parameter |
| * @param src Description of Parameter |
| * @param parameters Description of Parameter |
| * @return Description of the Returned Value |
| * @exception Exception Description of Exception |
| */ |
| public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String src, |
| Parameters parameters) |
| throws Exception { |
| DataSourceComponent datasource = null; |
| Connection conn = null; |
| Statement st = null; |
| ResultSet 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)); |
| String create_session = parameters.getParameter("create-session", |
| (String)this.settings.get("create-session")); |
| String append_session = parameters.getParameter("append-session", |
| (String)this.settings.get("append-session")); |
| boolean cs = true; |
| if (create_session != null) { |
| cs = BooleanUtils.toBoolean(create_session.trim()); |
| } |
| boolean as = BooleanUtils.toBoolean(append_session.trim()); |
| |
| datasource = this.getDataSource(conf); |
| conn = datasource.getConnection(); |
| Request req = ObjectModelHelper.getRequest(objectModel); |
| |
| /* |
| * check request validity |
| */ |
| if (req == null) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: no request object"); |
| } |
| return null; |
| } |
| |
| String query = this.getAuthQuery(objectModel, conf, req); |
| if (query == null) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: have not got query"); |
| } |
| req.setAttribute("message", "The authenticator is misconfigured"); |
| return null; |
| } |
| |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: query is: " + query); |
| } |
| st = conn.createStatement(); |
| rs = st.executeQuery(query); |
| |
| if (rs.next()) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: authorized successfully"); |
| } |
| Session session = null; |
| |
| if (cs) { |
| session = req.getSession(false); |
| if (session != null) { |
| if (as == false) { |
| session.invalidate(); |
| session = req.getSession(true); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: session invalidated"); |
| } |
| } |
| } else { |
| session = req.getSession(true); |
| } |
| |
| if (session == null) { |
| return null; |
| } |
| |
| if (getLogger().isDebugEnabled()) { |
| if (as) { |
| getLogger().debug("DBCOOKIEAUTH: appending to session"); |
| } else { |
| getLogger().debug("DBCOOKIEAUTH: session created"); |
| } |
| } |
| } else { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: leaving session untouched"); |
| } |
| } |
| |
| HashMap actionMap = this.propagateParameters(conf, rs, session); |
| if (!conn.getAutoCommit()) { |
| conn.commit(); |
| } |
| return Collections.unmodifiableMap(actionMap); |
| } |
| if (!conn.getAutoCommit()) { |
| conn.rollback(); |
| } |
| |
| req.setAttribute("message", "The username or password were incorrect, please check your CAPS LOCK key and try again."); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: no results for query"); |
| } |
| } catch (Exception e) { |
| if (conn != null) { |
| try { |
| if (!conn.getAutoCommit()) { |
| conn.rollback(); |
| } |
| } catch (Exception se) { |
| // ignore |
| } |
| } |
| getLogger().error("Exception: ", e); |
| return null; |
| } finally { |
| if (rs != null) { |
| rs.close(); |
| } |
| if (st != null) { |
| st.close(); |
| } |
| if (conn != null) { |
| try { |
| conn.close(); |
| } catch (Exception e) { |
| // ignore |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Gets the authQuery attribute of the DatabaseCookieAuthenticatorAction |
| * object |
| * |
| * @param objectModel Description of Parameter |
| * @param conf Description of Parameter |
| * @param req Description of Parameter |
| * @return The authQuery value |
| */ |
| private String getAuthQuery(Map objectModel, Configuration conf, Request req) { |
| boolean first_constraint = true; |
| StringBuffer queryBuffer = new StringBuffer("SELECT "); |
| StringBuffer queryBufferEnd = new StringBuffer(""); |
| String dbcol; |
| String cookie_name; |
| String cookie_value; |
| String nullstr; |
| boolean nullable = false; |
| Configuration table = conf.getChild("table"); |
| Configuration[] select = table.getChildren("select"); |
| try { |
| for (int i = 0; i < select.length; i++) { |
| if (i != 0) { |
| queryBuffer.append(", "); |
| } |
| dbcol = select[i].getAttribute("dbcol"); |
| queryBuffer.append(dbcol); |
| cookie_name = select[i].getAttribute("cookie-name", ""); |
| if (StringUtils.isEmpty(cookie_name.trim())) { |
| continue; |
| } |
| nullstr = select[i].getAttribute("nullable", ""); |
| if (BooleanUtils.toBoolean(nullstr.trim())) { |
| nullable = true; |
| } |
| /* |
| * if there is a cookie name, |
| * but not the value, we exit immediately do |
| * that authorization fails authomatically |
| */ |
| cookie_value = getCookie(objectModel, cookie_name).getValue(); |
| |
| if (cookie_value == null || cookie_value.trim().length() == 0) { |
| // value is null |
| if (!nullable) { |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: cookie-name " |
| + cookie_name + " does not exist"); |
| } |
| return null; |
| } |
| } else { |
| if (!first_constraint) { |
| queryBufferEnd.append(" AND "); |
| } |
| queryBufferEnd.append(dbcol + "='" + cookie_value + "'"); |
| first_constraint = false; |
| } |
| } |
| queryBuffer.append(" FROM "); |
| queryBuffer.append(table.getAttribute("name")); |
| if (!queryBufferEnd.toString().trim().equals("")) { |
| queryBuffer.append(" WHERE ").append(queryBufferEnd); |
| } |
| return queryBuffer.toString(); |
| } catch (Exception e) { |
| getLogger().error("Exception: ",e); |
| return null; |
| } |
| } |
| |
| public static Cookie getCookie(Map objectModel, String cookieName) { |
| |
| Request request = ObjectModelHelper.getRequest(objectModel); |
| |
| Cookie[] cookies = request.getCookies(); |
| if (cookies != null) { |
| for(int count = 0; count < cookies.length; count++) { |
| Cookie currentCookie = cookies[count]; |
| if (currentCookie.getName().equals(cookieName)) { |
| return currentCookie; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Description of the Method |
| * |
| * @param conf Description of Parameter |
| * @param rs Description of Parameter |
| * @param session Description of Parameter |
| * @return Description of the Returned Value |
| */ |
| private HashMap propagateParameters(Configuration conf, ResultSet rs, |
| Session session) { |
| Configuration table = conf.getChild("table"); |
| Configuration[] select = table.getChildren("select"); |
| String session_param; |
| HashMap map = new HashMap(); |
| 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 = rs.getString(i + 1); |
| /* |
| * propagate to session |
| */ |
| Object o = null; |
| String type = select[i].getAttribute("type", ""); |
| // "string" is the default type |
| if (StringUtils.isEmpty(type.trim()) || "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); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("DBCOOKIEAUTH: propagating param " |
| + session_param + "=" + s); |
| } |
| } |
| map.put(session_param, o); |
| } |
| } catch (Exception e) { |
| // ignore |
| } |
| } |
| return map; |
| } catch (Exception e) { |
| getLogger().error("Exception: ", e); |
| } |
| return null; |
| } |
| } |