users@glassfish.java.net

GFv3 Custom Principal

From: <glassfish_at_javadesktop.org>
Date: Wed, 12 May 2010 03:35:10 PDT

Hi,

I would like to use a Custom Principal and I changed the original JDBCLoginModule a new one.
It is working fine, but the custom principal is not used in the SessionContext
 sessionContext.getCallerPrincipal().getClass().getName() => org.glassfish.security.common.PrincipalImpl
what I need for it.

Thanks, Attila.

----------------------------------------------------------------------
package com.sun.enterprise.security.auth.login;

import java.util.Set;
import java.util.logging.Level;
import java.security.Principal;
import javax.security.auth.login.LoginException;
import org.glassfish.security.common.Group;
import com.sun.enterprise.security.auth.login.PasswordLoginModule;
import com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm;

/**
 * This class implement a JDBC Login module for Glassfish.
 * The work is derivated from Sun's sample JDBC login module.
 * Enhancement has been done to use latest features.
 * sample setting in server.xml for JDBCLoginModule
 * @author Jean-Baptiste Bugeaud
 */
public class CTJDBCLoginModule extends PasswordLoginModule {
    /**
     * Perform JDBC authentication. Delegates to JDBCRealm.
     *
     * @throws LoginException If login fails (JAAS login() behavior).
     */
    protected void authenticate() throws LoginException {
        if (!(_currentRealm instanceof JDBCRealm)) {
            String msg = sm.getString("jdbclm.badrealm");
            throw new LoginException(msg);
        }
            System.out.println("AUTHENTICATE: <"+_currentRealm.getName()+">("+_username+")["+_password+"]");
        
        final JDBCRealm jdbcRealm = (JDBCRealm)_currentRealm;

        // A JDBC user must have a name not null and non-empty.
        if ( (_username == null) || (_username.length() == 0) ) {
            String msg = sm.getString("jdbclm.nulluser");
            throw new LoginException(msg);
        }
        
        String[] grpList = jdbcRealm.authenticate(_username, _password);

        if (grpList == null) { // JAAS behavior
            String msg = sm.getString("jdbclm.loginfail", _username);
            throw new LoginException(msg);
        }

        if (_logger.isLoggable(Level.FINEST)) {
            _logger.finest("JDBC login succeeded for: " + _username
                + " groups:" + grpList);
        }

        //make a copy of groupList to pass to LoginModule. This copy is the one
        // that will be made null there. DO NOT PASS the grpList as is - as
        // it will get overwritten. Resulting in logins passing only once.
        final String[] groupListToForward = new String[grpList.length];
        System.arraycopy(grpList, 0, groupListToForward, 0, grpList.length);

        commitAuthentication(_username, _password,
                             _currentRealm, groupListToForward);
    }
    
    /**
     * Commit the authentication.
     *
     * <P>Commit is called after all necessary login modules have succeeded.
     * It adds (if not present) a PrincipalImpl principal and a
     * LocalCredentials public credential to the Subject.
     *
     * @throws LoginException If commit fails.
     *
     */
    @Override
    public boolean commit() throws LoginException
    {
        if (_succeeded == false) {
            return false;
        }
            System.out.println("COMMIT: <"+_currentRealm.getName()+">("+_username+")["+_password+"]");

        // Add a Principal (authenticated identity) to the Subject
        // Assume the user we authenticated is the PrincipalImpl [RI]
        _userPrincipal = new CTJDBCLoginModuleUser(_username);
        CTJDBCLoginModuleUser myUserPrincipal = new CTJDBCLoginModuleUser(_username);
        Set<Principal> principalSet = _subject.getPrincipals();
        if (!principalSet.contains(myUserPrincipal)){
            principalSet.add(myUserPrincipal);
        }
        /* populate the group in the subject and clean out the slate at the same
         * time
         */
        for(int i = 0; i<_groupsList.length; i++){
            if(_groupsList[i] != null){
                Group g = new Group(_groupsList[i]);
                if(!principalSet.contains(g)){
                    principalSet.add(g);
                }
                
                // cleaning the slate
                _groupsList[i] = null;
            }
        }
        // In any case, clean out state.
        _groupsList = null;
        _username = null;
        _password = null;
        _commitSucceeded = true;
        if(_logger.isLoggable(Level.FINE)){
            _logger.log(Level.FINE,"JAAS authentication committed.");
        }
        return true;
    }
}

-----------------------------------------------------------------------
package com.sun.enterprise.security.auth.login;

import java.util.*;

import org.glassfish.security.common.PrincipalImpl;
import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
import com.sun.enterprise.security.auth.realm.Realm;
import com.sun.enterprise.security.auth.realm.User;


/**
 * Represents a FileRealm user.
 *
 *
 */
@SuppressWarnings({"serial", "unchecked"})
public class CTJDBCLoginModuleUser extends PrincipalImpl implements User
{
// private static final String GROUP_KEY = "Groups"; // not needed
    private String[] groups;
    private String realm;
        private Hashtable attributes;

    
    /**
     * Constructor.
     *
     */
    public CTJDBCLoginModuleUser(String name)
    {
        super(name);
        this.realm = "default";
        this.groups = new String[0];
        attributes = new Hashtable(1); // not really needed
    }


    /**
     * Constructor.
     *
     * @param name User name.
     * @param groups Group memerships.
     * @param realm Realm.
     * @param salt SSHA salt.
     * @param hash SSHA password hash.
     *
     */
    public CTJDBCLoginModuleUser(String realm, String name, String[] groups )
    {
        this(name);
        this.realm = realm;
        this.groups = groups.clone();
        
        //attributes.put(GROUP_KEY, groups);
    }
    
    /**
     * Returns the realm with which this user is associated
     *
     * @return Realm name.
     * @exception NoSuchRealmException if the realm associated this user
     * no longer exist
     *
     */
    public Realm getRealm() throws NoSuchRealmException
    {
            return Realm.getInstance(realm);
    }


    /**
     * Return the names of the groups this user belongs to.
     *
     * @return String[] List of group memberships.
     *
     */
    public String[] getGroups()
    {
            return groups;
    }

    
    /**
     * Set group membership.
     *
     */
    public void setGroups(String[] grp)
    {
        this.groups = grp;
    }

    
    /**
     * Return the requested attribute for the user.
     * <P>Not really needed.
     *
     * @param key string identifies the attribute.
     */
    public Object getAttribute (String key)
    {
        return attributes.get(key);
    }

    
    /**
     * Return the names of the supported attributes for this user.
     * <P>Not really needed.
     */
        public Enumeration getAttributeNames () {
            return attributes.keys();
    }
    
}

-----------------------------
sun-application.xml
<sun-application>
  <security-role-mapping>
    <role-name>programmers</role-name>
    <principal-name class-name="com.sun.enterprise.security.auth.login.CTJDBCLoginModuleUser">programmer</principal-name>
    <group-name>developers</group-name>
   </security-role-mapping>
   <realm>helloRealm</realm>
</sun-application>

----------------------
sun-ejb-jar.xml
<sun-ejb-jar>
  <enterprise-beans>
      <ejb>
          <ejb-name>StatelessSessionBean</ejb-name>
          <ior-security-config>
              <as-context>
                   <auth-method>username_password</auth-method>
                   <realm>helloRealm</realm>
                   <required>true</required>
              </as-context>
          </ior-security-config>
      </ejb>
  </enterprise-beans>
</sun-ejb-jar>

--------------------------------------------------------------
package enterprise.hello_stateless_ejb;

import javax.ejb.Stateless;
import javax.ejb.SessionContext;
import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.interceptor.Interceptors;

@Stateless
public class StatelessSessionBean implements StatelessSession {

    @Resource
    private SessionContext sessionContext;

    @RolesAllowed("programmers")
    @Interceptors(StatelessInterceptor.class)
    @Override
    public String hello() {
        System.out.println("In HelloBean(Stateless)::hello()["+
                sessionContext.getCallerPrincipal().getClass().getName()+"]("+
                sessionContext.getCallerPrincipal().getName()+")");
        return "hello, world!\n";
    }

    @PermitAll
    @PostConstruct
    private void postConstruct() {
        System.out.println("In HelloBean(Stateless)::postConstruct()");
    }

    @PermitAll
    @PreDestroy
    private void preDestroy() {
        System.out.println("In HelloBean(Stateless)::preDestroy()");
    }

}
[Message sent by forum member 'aszomor']

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