users@glassfish.java.net

Re: Custom Realm Problems

From: <glassfish_at_javadesktop.org>
Date: Wed, 20 Feb 2008 23:30:42 PST

I can't find what's wrong with my custom realm implementation.
Notice that on each function I output a server log message so I can identify it, however non of those appear on the server log, only the error described previously.


Here are my files:

The Login Module class:
--------------------------------------------
package com.expolang.security.sunappserv;

import javax.security.auth.login.LoginException;
import com.sun.appserv.security.AppservPasswordLoginModule;
import java.util.logging.Level;

/**
 * Implements JAAS LoginModule as part of the ExpoLangRealm custom realm.
 */
public class ExpoLangLoginModule extends AppservPasswordLoginModule {

    @Override
    protected void authenticateUser() throws LoginException {
        _logger.log(Level.INFO, "ExpoLangLoginModule start");
        // Get the current realm and check whether it is instance of your realm
        if (!(_currentRealm instanceof ExpoLangRealm)) {
            throw new LoginException("ExpoLangLoginModule: Realm is not a ExpoLangRealm.");
        }

        
        ExpoLangRealm myCustomRealm = (ExpoLangRealm) _currentRealm;
        String[] grpList = myCustomRealm.authenticateUser(_username, _password);
        _logger.log(Level.INFO, "ExpoLangLoginModule after authenticateUser");

        if (grpList == null) // JAAS behavior
        {
            throw new LoginException("ExpoLangLoginModule: Login Failed with user " + _username);
        }

        // Database authentication:
        _logger.log(Level.FINE, "ExpoLangLoginModule returning groups");
        _logger.log(Level.WARNING, "ExpoLangLoginModule returning groups");
        commitUserAuthentication(grpList);
    }// authenticateUser()
}// class ExpoLangLoginModule
--------------------------------------------


The Realm class:
--------------------------------------------
package com.expolang.security.sunappserv;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import com.sun.appserv.security.AppservRealm;
import com.sun.enterprise.security.auth.realm.BadRealmException;
import com.sun.enterprise.security.auth.realm.NoSuchUserException;
import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
import com.sun.enterprise.security.auth.realm.InvalidOperationException;

/**
 * ExpoLangRealm for supporting RDBMS authentication.
 *
 * sample setting in domain.xml for ExpoLangeLoginModule
 * <auth-realm name="ExpoLangRealm" classname="com.expolang.security.expolangrealm">
 * <property name="dbdrivername" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
 * <property name="dburl" value="jdbc:sqlserver://192.168.0.101:1433;databaseName=ExpoLang"/>
 * <property name="dbusername" value="public"/>
 * <property name="dbpasswd" value="public"/>
 * <property name="dbauthfunction" value="dbfunc"/>
 * </auth-realm>
 */
public final class ExpoLangRealm extends AppservRealm {

    static final String AUTH_TYPE = "ExpoLangRealm";
    static final String AUTH_TYPE_PARAM = "auth-type";
    private String authType = null;
    static final String PARAMS_DBDRIVERNAME = "dbdrivername";
    private String dbDriverName = null;
    static final String PARAMS_DBURL = "dburl";
    private String dbUrl = null;
    static final String PARAMS_DBUSERNAME = "dbusername";
    private String dbUsername = null;
    static final String PARAMS_DBPASSWD = "dbpasswd";
    private String dbPassword = null;
    static final String PARAMS_DBAUTHFUNCTION = "dbauthfunction";
    private String dbAuthFunction = null;
    
    
    private Properties _realmProperties = null;
    private Vector<String> _emptyVector;
    private String[] _emptyStringArray;
    
    static Driver _dbdriver = null;
    static Connection _dbConnection = null;

    /*
    public ExpoLangRealm() {
    }// ExpoLangRealm()
    */
    
    
    /**
     * Initialize a realm with some properties. This can be used
     * when instantiating realms from their descriptions. This
     * method may only be called a single time.
     *
     * @param props Initialization parameters used by this realm.
     * @exception BadRealmException If the configuration parameters
     * identify a corrupt realm.
     * @exception NoSuchRealmException If the configuration parameters
     * specify a realm which doesn't exist.
     *
     */
    @Override
    protected void init(Properties props)
            throws BadRealmException, NoSuchRealmException {
        super.init(props);
        _realmProperties = props;
        _emptyVector = new Vector<String>();
        _emptyStringArray = new String[0];

        String jaasCtx = props.getProperty(AppservRealm.JAAS_CONTEXT_PARAM);
        this.setProperty(AppservRealm.JAAS_CONTEXT_PARAM, jaasCtx);

        // Load realm properties:
        try {
            authType = getProp(AUTH_TYPE_PARAM);
        } catch (BadRealmException bre) {
            authType = AUTH_TYPE;
        }

        dbDriverName = getProp(PARAMS_DBDRIVERNAME);
        dbUrl = getProp(PARAMS_DBURL);
        dbUsername = getProp(PARAMS_DBUSERNAME);
        dbPassword = getProp(PARAMS_DBPASSWD);
        dbAuthFunction = "{call " + getProp(PARAMS_DBAUTHFUNCTION) + "(?, ?)}";

        System.out.println("\nExpoLangRealm initialized successfuly.\n");
    }// init(Properties)
    private String getProp(String propertyName) throws BadRealmException {
        String propValue = _realmProperties.getProperty(propertyName);
        if (propValue == null) {
            throw new BadRealmException("Field " + propertyName + " does not exist in realm configuration.");
        }

        return propValue;
    }// String getProp(String)
    /**
     * Returns a short description of the kind of authentication which is
     * supported by this realm.
     *
     * @return Description of the kind of authentication that is directly
     * supported by this realm.
     */
    @Override
    public String getAuthType() {
        System.out.println("ExpoLangRealm: using getAuthType()");
        return this.authType;
    }// String getAuthType()
    /**
     * Returns the name of all the groups that this user belongs to.
     * @param username Name of the user in this realm whose group listing
     * is needed.
     * @return Enumeration of group names (strings).
     * @exception InvalidOperationException thrown if the realm does not
     * support this operation - e.g. Certificate realm does not support
     * this operation.
     */
    public Enumeration<String> getGroupNames(String username)
            throws InvalidOperationException, NoSuchUserException {
        System.out.println("\nExpoLangRealm getGroupNames(String username = " + username + ")\n");
        
        Vector<String> x = new Vector<String>();
        x.add("ExpoLang");
        return x.elements();
        //return _emptyVector.elements();
    }// Enumeration<String> getGroupNames(String)
    /**
     * Return the user group associated with the specified username and
     * credentials, if there is one; otherwise return <code>null</code>.
     *
     * @param username
     * the user's id
     * @param passwd
     * the user's clear password
     */
    public String[] authenticateUser(String username, String passwd) {
        System.out.println("Begin authenticating " + username + "...");

        ArrayList<String> userGroups = new ArrayList<String>();
        CallableStatement cs = null;
        try {
            Connection conn = getConnection();

            cs = conn.prepareCall(dbAuthFunction);
            cs.setString(1, username);
            cs.setString(2, passwd);
            ResultSet rs = cs.executeQuery();

            String group;
            while (rs.next()) {
                group = rs.getString(1).trim();
                if (!userGroups.contains(group)) {
                    userGroups.add(group);
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("ExpoLangRealm: Error connecting to database.");

        } finally {
            try {
                cs.close();
            } catch (SQLException ignore) {
                ignore.printStackTrace();
            }
        }

        System.out.println("ExpoLangRealm: Finished authenticating. Size of array: " + userGroups.size());
        return userGroups.toArray(_emptyStringArray);
    }// String[] authenticate(String, String)
    /**
     * Get JDBC connection.
     */
    private Connection getConnection() throws SQLException {
        if (_dbConnection != null) {
            return (_dbConnection);
        }

        String dbdrivername = dbDriverName;
        String dburl = dbUrl;
        String dbusername = dbUsername;
        String dbpasswd = dbPassword;

        if (_dbdriver == null) {
            try {
                Class<?> clazz = Class.forName(dbdrivername);
                _dbdriver = (Driver) clazz.newInstance();
            } catch (Throwable e) {
                throw new SQLException(e.getMessage());
            }
        }

        // Open a new connection
        Properties props = new Properties();
        props.put("user", dbusername);
        props.put("password", dbpasswd);

        Connection dbcon = _dbdriver.connect(dburl, props);
        dbcon.setAutoCommit(false);
        return dbcon;
    }// Connection getConnection()
}// class ExpoLangRealm
--------------------------------------------


Thanks alot for helping!
[Message sent by forum member 'bobohaskel' (bobohaskel)]

http://forums.java.net/jive/thread.jspa?messageID=260105