Package org.apache.isis.security.sql.authentication

Source Code of org.apache.isis.security.sql.authentication.SqlAuthenticator

/*
*  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.isis.security.sql.authentication;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

import com.google.common.base.Strings;
import com.google.inject.Inject;

import org.apache.log4j.Logger;

import org.apache.isis.applib.ApplicationException;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.ensure.Assert;
import org.apache.isis.core.runtime.authentication.AuthenticationRequest;
import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
import org.apache.isis.core.runtime.authentication.standard.PasswordRequestAuthenticatorAbstract;
import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;

public class SqlAuthenticator extends PasswordRequestAuthenticatorAbstract {
    private static final Logger LOG = Logger.getLogger(SqlAuthenticator.class);

    static SqlAuthenticator instance;

    public static SqlAuthenticator getInstance() {
        return instance;
    }

    // Override this method if dbPasswords are encoded.
    protected boolean verifyPasswordsAreEqual(final String loginPassword, final String dbPassword) {
        return dbPassword.equals(loginPassword);
    }

    // Override this method
    protected ResultSet postProcessLogin(final String user, final String password, final ResultSet results) {
        return results;
    }

    // override this method
    protected String getRoles(final ResultSet results, final String roles) {
        try {
            if (userRoleField != null) {
                final String dbRoles = results.getString(userRoleField);
                return roles + "|" + dbRoles;
            }
        } catch (final SQLException e) {
            LOG.warn("Error fetching role", e);
        }
        return roles;
    }

    // Override this method, if you want to create data.
    public void initialise() {
    }

    static final String PROPERTY_BASE = "isis.authentication.sql";
    static final String USER_TABLE = PROPERTY_BASE + ".userTable";
    static final String USER_TABLE_NAME_FIELD = PROPERTY_BASE + ".userNameField";
    static final String USER_TABLE_PASSWORD_FIELD = PROPERTY_BASE + ".passwordField";
    static final String USER_TABLE_ROLE_FIELD = PROPERTY_BASE + ".roleField";

    private Connection connection;

    final String passwordField;
    final String userTable;
    final String userNameField;
    final String userRoleField;

    public static String getPropertyBase() {
        return PROPERTY_BASE;
    }

    public static String getPropertyUserTable() {
        return USER_TABLE;
    }

    public static String getPropertyUserTableNameField() {
        return USER_TABLE_NAME_FIELD;
    }

    public static String getPropertyUserTablePasswordField() {
        return USER_TABLE_PASSWORD_FIELD;
    }

    public static String getPropertyUserTableRoleField() {
        return USER_TABLE_ROLE_FIELD;
    }

    @Inject
    public SqlAuthenticator(final IsisConfiguration configuration) {
        super(configuration);

        userTable = configuration.getString(USER_TABLE);
        userNameField = configuration.getString(USER_TABLE_NAME_FIELD);
        passwordField = configuration.getString(USER_TABLE_PASSWORD_FIELD);
        userRoleField = configuration.getString(USER_TABLE_ROLE_FIELD);

        instance = this;
    }

    @Override
    public void init() {
        if (connection != null) {
            LOG.info("close");
        }

        final String BASE = PROPERTY_BASE + ".jdbc.";
        final IsisConfiguration params = IsisContext.getConfiguration().getProperties(BASE);

        try {
            final String driver = params.getString(BASE + "driver");
            final String url = params.getString(BASE + "connection");
            final String user = params.getString(BASE + "user");
            final String password = params.getString(BASE + "password");

            if (connection != null) {
                throw new ApplicationException("Connection already established");
            }

            if (driver == null) {
                throw new ApplicationException("No driver specified for database connection");
            }
            if (url == null) {
                throw new ApplicationException("No connection URL specified to database");
            }
            if (user == null) {
                throw new ApplicationException("No user specified for database connection");
            }
            if (password == null) {
                throw new ApplicationException("No password specified for database connection");
            }

            Class.forName(driver);
            LOG.info("Connecting to " + url + " as " + user);
            connection = DriverManager.getConnection(url, user, password);
            if (connection == null) {
                throw new ApplicationException("No connection established to " + url);
            }
        } catch (final SQLException e) {
            throw new ApplicationException("Failed to start", e);
        } catch (final ClassNotFoundException e) {
            throw new ApplicationException("Could not find database driver", e);
        }

    }

    @Override
    public void shutdown() {
        String sql;
        sql = "SHUTDOWN";
        update(sql);
        closeConnection();
    }

    private void closeConnection() {
        try {
            connection.close();
            connection = null;
        } catch (final SQLException e) {
            LOG.warn("Failed to close connection:" + e);
        }
    }

    @Override
    public final boolean isValid(final AuthenticationRequest request) {
        final AuthenticationRequestPassword passwordRequest = (AuthenticationRequestPassword) request;
        final String username = passwordRequest.getName();
        if (Strings.isNullOrEmpty(username)) {
            return false;
        }
        final String password = passwordRequest.getPassword();
        Assert.assertNotNull(password);

        return isPasswordValidForUser(passwordRequest, username, password);

    }

    private boolean isPasswordValidForUser(final AuthenticationRequest request, final String user, final String password) {
        final ResultSet results = loadUserDetails(user, password);
        if (results != null) {
            final String roles = getRoles(results, "org.apache.isis.viewer.wicket.roles.USER|org.starobjects.wicket.roles.USER");
            setRoles(request, roles);

            return true;
        }
        return false;
    }

    protected ResultSet loadUserDetails(final String user, final String password) {
        final String sql = "SELECT * FROM " + userTable + " WHERE UPPER(" + userNameField + ") = ?";
        addToQueryValues(user.toUpperCase());
        final ResultSet results = select(sql);
        try {
            while (results.next()) {
                final String dbPassword = results.getString(passwordField);
                if (verifyPasswordsAreEqual(password, dbPassword)) {
                    return postProcessLogin(user, password, results);
                }
            }
        } catch (final SQLException e) {
            LOG.error("Error loading user details: " + sql);
            throw new ApplicationException("Error loading user details", e);
        }

        return null;
    }

    private final void setRoles(final AuthenticationRequest request, final String line) {
        final StringTokenizer tokens = new StringTokenizer(line, "|", false);
        final String[] roles = new String[tokens.countTokens()];
        for (int i = 0; tokens.hasMoreTokens(); i++) {
            roles[i] = tokens.nextToken();
        }
        request.setRoles(Arrays.asList(roles));
    }

    public boolean isSetup() {
        return hasTable(userTable);
    }

    // {{ JDBC Connection SQL helpers
    protected int update(final String sql) {
        LOG.debug("SQL: " + sql);
        PreparedStatement statement;
        try {
            statement = connection.prepareStatement(sql);
            addPreparedValues(statement);
            final int updateCount = statement.executeUpdate();
            statement.close();
            return updateCount;
        } catch (final SQLException e) {
            LOG.error("failed to execute " + sql, e);
            throw new ApplicationException("Error executing update", e);
        } finally {
            clearPreparedValues();
        }

    }

    private ResultSet select(final String sql) {
        LOG.debug("SQL: " + sql);
        PreparedStatement statement;
        try {
            statement = connection.prepareStatement(sql);
            addPreparedValues(statement);
            return (statement.executeQuery());
        } catch (final SQLException e) {
            LOG.error("failed to execte select: " + sql, e);
            throw new ApplicationException("Error executing select", e);
        } finally {
            clearPreparedValues();
        }
    }

    private final List<Object> queryValues = new ArrayList<Object>();

    public String addToQueryValues(final Object o) {
        queryValues.add(o);
        return "?";
    }

    private void clearPreparedValues() {
        queryValues.clear();
    }

    private void addPreparedValues(final PreparedStatement statement) throws SQLException {
        if (queryValues.size() > 0) {
            int i = 1;
            try {
                for (final Object value : queryValues) {
                    statement.setObject(i, value);
                    i++;
                }
            } catch (final SQLException e) {
                LOG.error("Error adding prepared value " + i + " of type " + queryValues.get(i - 1).getClass().getSimpleName(), e);
                throw e;
            }
        }
    }

    private boolean hasTable(final String tableName) {
        try {
            final ResultSet set = connection.getMetaData().getTables(null, null, tableName, null);
            if (set.next()) {
                LOG.debug("Found " + set.getString("TABLE_NAME"));
                set.close();
                return true;
            } else {
                set.close();
                return false;
            }
        } catch (final SQLException e) {
            LOG.error("failed to find table: " + tableName, e);
            throw new ApplicationException("Error checking for table: " + tableName, e);
        }
    }

    // }}

}
TOP

Related Classes of org.apache.isis.security.sql.authentication.SqlAuthenticator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.