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