All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kawanfw.commons.api.server.DefaultCommonsConfigurator Maven / Gradle / Ivy

Go to download

Awake FILE is a secure Open Source framework that allows to program very easily file uploads/downloads and RPC through http. File transfers include powerful features like file chunking and automatic recovery mechanism. Security has been taken into account from the design: server side allows to specify strong security rules in order to protect the files and to secure the RPC calls.

The newest version!
/*
 * This file is part of Awake FILE. 
 * Awake file: Easy file upload & download over HTTP with Java.                                    
 * Copyright (C) 2015,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.                                
 *                                                                               
 * Awake FILE is free software; you can redistribute it and/or                 
 * modify it under the terms of the GNU Lesser General Public                    
 * License as published by the Free Software Foundation; either                  
 * version 2.1 of the License, or (at your option) any later version.            
 *                                                                               
 * Awake FILE is distributed in the hope that it will be useful,               
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             
 * Lesser General Public License for more details.                               
 *                                                                               
 * You should have received a copy of the GNU Lesser General Public              
 * License along with this library; if not, write to the Free Software           
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
 * 02110-1301  USA
 *
 * Any modifications to this file must keep this entire header
 * intact.
 */
package org.kawanfw.commons.api.server;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.kawanfw.commons.api.server.util.HttpServletRequestStore;
import org.kawanfw.commons.api.server.util.ServerInfo;
import org.kawanfw.commons.api.server.util.Sha1;
import org.kawanfw.commons.api.server.util.SingleLineFormatter;
import org.kawanfw.commons.server.util.ServerLogger;
import org.kawanfw.commons.server.util.embed.TomcatModeStore;
import org.kawanfw.commons.util.FrameworkFileUtil;
import org.kawanfw.commons.util.Tag;

/**
 * 
 * Default implementation of the commons User Configuration for the KawanSoft
 * Frameworks.
 * 

* This defaults implementation will help for a quick start and to test the * KawanSoft Frameworks, but please note that is implementation is not secure * at all.
* Especially: the login method will always return * true. *

* So: *

    *
  • The forceSecureHttp method should be set to true by your * implementation in order to prevent the login info and the data to be send in * clear over the Internet with http protocol * frameworks.
  • *
  • The login method should be overridden by your specific * implementation or using {@link SshAuthCommonsConfigurator} implementation.
  • *
*

* * @see org.kawanfw.commons.api.server.SshAuthCommonsConfigurator * @author Nicolas de Pomereu * @since 1.0 */ public class DefaultCommonsConfigurator implements CommonsConfigurator { /** The Logger to use */ private static Logger KAWANFW_LOGGER = null; /** The data source to use for connection pooling */ private DataSource dataSource = null; /** Cache the addSecretForAuthToken() value */ private String secretForAuthAdded = null; /** * Default Constructor. */ public DefaultCommonsConfigurator() { } /** * @return false. (Client programs will be allowed to send * unsecured http requests). */ @Override public boolean forceSecureHttp() { return false; } /** * @return Empty HashSet. (No banned IP usernames.) */ @Override public Set getBannedUsernames() throws IOException, SQLException { return new HashSet(); } /** * @return Empty ArrayList. (No IP addresses are * blacklisted.) */ @Override public List getIPsBlacklist() throws IOException, SQLException { return new ArrayList(); // Empty ArrayList } /** * @return Empty ArrayList. (All IP addresses are * accepted.) */ @Override public List getIPsWhitelist() throws IOException, SQLException { return new ArrayList(); // Empty ArrayList } /** * @return true. (Client is always granted access). */ @Override public boolean login(String username, char[] password) throws IOException, SQLException { return true; } /** * * Returns a {@code Connection} from Tomcat * JDBC Connection Pool.
*
* How the {@code Connection} is extracted depends on KawanSoft framework in use: *

    *
  • SQL framework: the {@code Connection} is extracted from the * {@code DataSource} created by the embedded Tomcat JDBC Pool. The JDBC * parameters used to create the {@code DataSource} are defined in the * properties file passed at start-up of the SQL Framework.
  • *
  • FILE framework: the {@code Connection} is extracted from the * {@code DataSource} created by an org.apache.tomcat.jdbc.pool.DataSourceFactory factory * defined as a {@code 'jdbc/kawanfw-default'} Resource in {@code server.xml} * or {@code context.xml}.
    * Here is an example: context.xml
  • *
* * * @return the {@code Connection} extracted from Tomcat JDBC Connection * Pool. */ @Override public Connection getConnection() throws SQLException { if (dataSource == null) { String servletName = getServletNameFromServletPath(); if (TomcatModeStore.isFrameworkSql()) { // SQL Software dataSource = TomcatModeStore.getDataSource(servletName); if (dataSource == null) { if (TomcatModeStore.isTomcatEmbedded()) { String message = Tag.PRODUCT_USER_CONFIG_FAIL + " the \"driverClassName\" property is not defined in the properties file for servlet " + servletName; ServerLogger.getLogger().log(Level.WARNING, message); throw new SQLException(message); } else { String message = Tag.PRODUCT_USER_CONFIG_FAIL + " the \"driverClassName\" property is not defined in the properties file for servlet " + servletName + " or the servlet name does not match the url pattern in your web.xml"; ServerLogger.getLogger().log(Level.WARNING, message); throw new SQLException(message); } } } else { // FILE Software String defaultResourceName = "jdbc/kawanfw-default"; try { Context initCtx0 = (Context) new InitialContext() .lookup("java:comp/env"); dataSource = (DataSource) initCtx0 .lookup(defaultResourceName); } catch (NamingException e) { String message = Tag.PRODUCT_USER_CONFIG_FAIL + " Invalid configuration. Lookup failed on Resource: " + defaultResourceName + " Reason: " + e.getMessage(); throw new SQLException(message, e); } } } Connection connection = dataSource.getConnection(); return connection; } /** * Returns the current executing servlet name extracted from the servlet path * @return the current executing servlet name extracted from the servlet path */ private String getServletNameFromServletPath() { HttpServletRequestStore httpServletRequestStore = new HttpServletRequestStore(); HttpServletRequest httpServletRequest= httpServletRequestStore.getHttpServletRequest(); String servletName = httpServletRequest.getServletPath(); servletName = servletName.trim(); servletName = StringUtils.substringAfterLast(servletName, "/"); return servletName; } /** * Returns a concatenation of server specific values that won't change * during the JVM life and that client side can not guess in order to secure * {@code computeAuthToken()}. *

* To ensure very strong security:
* this method should be overidden to * return this method return value plus a secret value in your * {@code CommonsConfigurator.addSecretForAuthToken()} implementation. *

* Example:

* *
     * @Override
     * public String addSecretForAuthToken() throws IOException, SQLException {
     *     return (super.addSecretForAuthToken() + "my secret value");
     * }
     * 
* *
* * @return the concatenation of some server specific values that won't * change during the JVM life and that the client side can not * guess: server MAC address + System properties: {@code user.home + * os.name + os.version + os.arch + java.class.path + * java.endorsed.dirs}. */ @Override public String addSecretForAuthToken() throws IOException, SQLException { if (secretForAuthAdded != null) { return secretForAuthAdded; } StringBuilder sb = new StringBuilder(); appendPropertySecure(sb, "ServerInfo.getMacAddress()"); // Should be authorized by Servlet Security Manager appendPropertySecure(sb, "java.home"); appendPropertySecure(sb, "os.name"); appendPropertySecure(sb, "os.version"); appendPropertySecure(sb, "os.arch"); // Try to add impossible to guess java.class.path & java.endorsed.dirs appendPropertySecure(sb, "java.class.path"); appendPropertySecure(sb, "java.endorsed.dirs"); // Cache it! secretForAuthAdded = sb.toString(); return secretForAuthAdded; } /** * Append to a {@code StringBuffer} a value and log the operation in case an excepton is thrown. * * @param sb the {@code StringBuffer} to append value on * @param property the property surname * */ private void appendPropertySecure(StringBuilder sb, String property) { String value = null; try { // Our own property if (property.equals("ServerInfo.getMacAddress()")) { value = ServerInfo.getMacAddress(); } else { // System properties value = System.getProperty(property); } sb.append(value); } catch (Exception e) { System.err.println(Tag.PRODUCT + " Caught an Exception in addSecretForAuthToken() calling " + property + ": " + value + ". " + e.toString()); } } /** * * This default method is secure if client side always use SSL/TLS httpS * calls.
*
* You may override the method if you want to create the Authentication * Token with your own security rules (adding random values stored in * database, etc.) * * @return SHA-1(username + secretValue) first 20 hexadecimal * characters.
*
* where: *
    *
  • username: the username of the client.
  • *
  • secretValue: the value returned by * {@link #addSecretForAuthToken()}.
  • *
* @throws Exception * if any Exception occurs */ @Override public String computeAuthToken(String username) throws Exception { return defaultComputeAuthToken(username, addSecretForAuthToken()); } /** * The default algorithm to use for computing token * * @param username * the client side username * @param secretForAuthToken * the secret to add * @return SHA-1(username + {@link #addSecretForAuthToken()}) * first 20 hexadecimal characters. * * @throws Exception if any Exception occurs */ public static String defaultComputeAuthToken(String username, String secretForAuthToken) throws Exception { // Add more secret info very hard to find for an external hacker StringBuilder tokenBuilder = new StringBuilder(); tokenBuilder.append(username); if (secretForAuthToken != null) { tokenBuilder.append(secretForAuthToken); } Sha1 hashcode = new Sha1(); String token = hashcode .getHexHash((tokenBuilder.toString()).getBytes()); token = StringUtils.left(token, 20); return token; } /** * @return null. It is highly recommended to override * this method in order to set a secret password in order to * reinforce the security of the transport of request parameters. */ @Override public char[] getEncryptionPassword() { return null; } /** * @return a Logger whose pattern is located in * user.home/.kawansoft/log/kawanfw.log, that uses a * {@link SingleLineFormatter} and that logs 50Mb into 4 rotating * files. */ @Override public Logger getLogger() throws IOException { if (KAWANFW_LOGGER == null) { File logDir = new File(FrameworkFileUtil.getUserHomeDotKawansoftDir() + File.separator + "log"); logDir.mkdirs(); String logFilePattern = logDir.toString() + File.separator + "kawanfw.log"; KAWANFW_LOGGER = Logger.getLogger("KawanfwLogger"); int limit = 50 * 1024 * 1024; Handler fh = new FileHandler(logFilePattern, limit, 4, true); fh.setFormatter(new SingleLineFormatter(false)); KAWANFW_LOGGER.addHandler(fh); } return KAWANFW_LOGGER; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy