-
1. Re: getting Custom Principal in EJBContext.getCallerPrincipa
tang Feb 26, 2004 8:57 AM (in response to nithila)I have also this problem and I checked my Subject was correctly filled. Is there a solution?? Or could you at least say me if it is not possible as I have been searching the solution for a while now.
My commit method is like this:
public boolean commit() throws LoginException {
if(subject != null)
{
Set principals = subject.getPrincipals();
if(principals != null)
{
principals.add(caller);
Group callerPrincipal = new SimpleGroup("CallerPrincipal");
callerPrincipal.addMember(caller);
principals.add(callerPrincipal);
// Set the roles for this principal in the 'Roles' group
Group group = new SimpleGroup("Roles");
group.addMember(new SimplePrincipal("JBossAdmin"));
principals.add(group);
return true;
}
}
return false;
}
caller is a TestPrincipal created in the login method if it succeeded. This is only a test that's why I don't look for the roles of the user and I declare him as a JBossAdmin. Is that a problem? I know there is a lot of post about this porblem but none could help me.
Thank you -
2. Re: getting Custom Principal in EJBContext.getCallerPrincipa
phantom Mar 1, 2004 11:26 AM (in response to nithila)Hello
I have the same problem. Please, anybody - answer! This quite important question in my view.
Thank you -
3. Re: getting Custom Principal in EJBContext.getCallerPrincipa
starksm64 Mar 2, 2004 12:55 AM (in response to nithila)This works fine for me. I have updated the UsernamePasswordLoginModule baseclass to support an external Principal implementation and added a testcase that uses a custom principal class and this is seen as the ejb getCallerPrincipal type:
public class CustomPrincipalBean implements SessionBean { ... public boolean validateCallerPrincipal(Class type) { ClassLoader typeLoader = type.getClassLoader(); log.info("validateCallerPrincipal, type="+type+", loader="+typeLoader); Principal caller = ctx.getCallerPrincipal(); log.info("caller="+caller+", class="+caller.getClass()); boolean isType = true; if( caller.getClass().isAssignableFrom(type) == false ) { log.error("type of caller is not: "+type); isType = false; } ...
This produces output like:
22:31:21,497 INFO [CustomPrincipalBean] validateCallerPrincipal, type=class org.jboss.test.security.ejb.CustomPrincipalImpl, loader=org.jboss.mx.loading.UnifiedClassLoader3@161f888{ url=file:/C:/cvs/JBoss3.2/jboss-3.2/build/output/jboss-3.
2.4RC1/server/default/tmp/deploy/tmp52272security-jaas.jar ,addedOrder=37}
22:31:21,497 INFO [CustomPrincipalBean] caller=callerJduke, class=class org.jboss.test.security.ejb.CustomPrincipalImpl -
4. Re: getting Custom Principal in EJBContext.getCallerPrincipa
phantom Mar 2, 2004 4:24 AM (in response to nithila)Let me explain error:
in MyLoginModule commit method:Set principals = subject.getPrincipals(); principals.add(new UserPrincipal(name)); for (Iterator it = principals.iterator(); it.hasNext();) { Principal principal = (Principal) it.next(); } Role role = new Role("Roles"); role.addMember(userPrincipal); principals.add(role);
UserPrincipal difined aspublic class UserPrincipal extends SimplePrincipal
Role defined aspublic class Role extends SimpleGroup
test.jsp has such code<%="principal: "+request.getUserPrincipal()%><br> <%="class: "+request.getUserPrincipal().getClass().getName()%><br>
After logining a have such lines in test.jsp output:principal: qwe class: org.jboss.security.SimplePrincipal
I use JBOSS+tomcat but if check principals in EJB - result is the same...:(
Please help me to find out a mistake!:) -
5. Re: getting Custom Principal in EJBContext.getCallerPrincipa
tang Mar 2, 2004 8:59 AM (in response to nithila)Normally, to get the right CallerPricipal via the ejb getCallerPrincipal method or via the Servlet getUserPrincipal, you have to fill the subject like I did in my post earlier in this thread (look at my commit method).
It is to say you got to fill it with your CallerPrincipal (you did) with a group containing the roles (you did) and also with a group called CallerPrincipal containing your UserPrincipal. The getCallerPrincipal method is supposed to return the Principal contained by the group called "CallerPrincipal". Maybe you did it but I didn't see it in your commit method.
But, I did that and it still doesn't work. For most people's problem it seems to be the solution, but not for mine. starksm, I suppose my commit method is fine, and when I check my subject I get this:
TestPrincipal: Name--> Tang class: securite.TestPrincipal
CallerPrincipal (members:TestPrincipal: Name--> Tang) class: org.jboss.security.SimpleGroup
Roles (members:JBossAdmin) class: org.jboss.security.SimpleGroup
So my subject seems to be successfully filled. Do you have an other idea why I have this problem??
Excuse my english! -
6. Re: getting Custom Principal in EJBContext.getCallerPrincipa
starksm64 Mar 2, 2004 9:34 AM (in response to nithila)Look at the jboss codebase for the org.jboss.security.auth.spiUsersRolesLoginModule and its base class org.jboss.security.auth.spi.UsernamePasswordLoginModule in the jboss-3.2/security/src/main tree for the commit behavior used with the example testcase. It will take 24 hours for this code to be available via anonymous cvs, try it at that time.
-
7. Re: getting Custom Principal in EJBContext.getCallerPrincipa
phantom Mar 2, 2004 9:55 AM (in response to nithila)Thank you.
I'll test changes...
But could you explain some interesting lines from sources?ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class clazz = loader.loadClass(identityClassName); Class[] ctorSig = {String.class}; Constructor ctor = clazz.getConstructor(ctorSig); Object[] ctorArgs = {username}; p = (Principal) ctor.newInstance(ctorArgs);
Why i can't do like this?Class clazz = Class.forName(...); Constructor ctor = clazz.getConstructor(new Class[]{String.class}); p = (Principal) ctor.newInstance(new Object[]{username});
Why I must use class loader to load a class?
Thank you a lot... -
8. Re: getting Custom Principal in EJBContext.getCallerPrincipa
phantom Mar 2, 2004 10:20 AM (in response to nithila)Let me add some information. It may be helpful.
We used some time ago weblogic and now we are "translating" our code to JBOSS. And there is one important point - SECURITY. We are tring to remake security using JAAS tchnology.... And we used java.security.LoginModule to create new LoginModule for JBOSS but not UsernamePasswordLoginModule (May be we are on a wrong way?). And this is our LoginModule:package XXXXXX.security; import org.jboss.logging.Logger; import org.jboss.security.NestableGroup; import javax.security.auth.login.LoginException; import javax.security.auth.Subject; import javax.security.auth.spi.LoginModule; import javax.security.auth.callback.*; import java.util.Map; import java.util.Set; import java.util.Iterator; import java.io.IOException; import java.security.acl.Group; import java.security.Principal; public class XXXXXXLoginModule implements LoginModule { private Subject subject = null; private CallbackHandler callbackHandler = null; private Map sharedState=null; private Map options=null; private boolean useFirstPass = false; private boolean loginOK = false; private UserPrincipal userPrincipal = null; private static final Logger log = Logger.getLogger(XXXXXXLoginModule.class); public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = options; String passwordStacking = (String) options.get("password-stacking"); if( passwordStacking != null && passwordStacking.equalsIgnoreCase("useFirstPass") ) useFirstPass = true; log.debug("initialized! caller = "+callbackHandler.getClass().getName()); log.debug("subject = "+subject.getClass().getName()); } public boolean login() throws LoginException { String[] info = getUserAndPassword(); userPrincipal = new UserPrincipal(info[0]); loginOK = info[0]==null?false:info[0].equals(info[1]); log.debug("loginOK="+loginOK); return loginOK; } public boolean abort() throws LoginException { return true; } public boolean commit() throws LoginException { if(loginOK) { Set principals = subject.getPrincipals(); principals.add(userPrincipal); for (Iterator it = principals.iterator(); it.hasNext();) { Principal principal = (Principal) it.next(); } Role role = new Role("Roles"); role.addMember(userPrincipal); principals.add(role); log.debug("Added "+userPrincipal+" class: "+userPrincipal.getClass().getName()+" to group "+role.getName()); return true; } else { return false; } } public boolean logout() throws LoginException { subject.getPrincipals(UserPrincipal.class).remove(userPrincipal); return true; } private String[] getUserAndPassword() throws LoginException { String[] ret = new String[2]; if(callbackHandler==null) { throw new LoginException("Callback handler = null"); } NameCallback nameCallback = new NameCallback("Name:","guest"); PasswordCallback passwordCallback = new PasswordCallback("Password:",false); try { callbackHandler.handle(new Callback[]{nameCallback,passwordCallback}); String name = nameCallback.getName(); String password = null; char[] tmpPassword = passwordCallback.getPassword(); char[] tmpPassword2 = new char[tmpPassword.length]; System.arraycopy(tmpPassword,0,tmpPassword2,0,tmpPassword.length); password=new String(tmpPassword2); ret[0]=name; ret[1]=password; } catch (IOException e) { throw new LoginException("Can't handle callbacks: "+e); } catch (UnsupportedCallbackException e) { throw new LoginException("Can't handle callbacks: "+e); } return ret; } protected Group createGroup(String name, Set principals) { Group roles = null; Iterator iter = principals.iterator(); while( iter.hasNext() ) { Object next = iter.next(); if( (next instanceof Group) == false ) continue; Group grp = (Group) next; if( grp.getName().equals(name) ) { roles = grp; break; } } // If we did not find a group create one if( roles == null ) { roles = new Role(name); principals.add(roles); } return roles; } }
Subject was created corretly(?). I check this by:<% Subject subject = SecurityAssociation.getSubject(); Iterator it = subject.getPrincipals().iterator(); out.println("subject!"); while (it.hasNext()) { Object o = (Object) it.next(); out.println("object="+o+" "); out.println("class="+o.getClass().getName()+"<br>"); } %>
result:subject: object=qwe class=XXXXXX.security.UserPrincipal object=Roles(members) class=XXXXXX.security.Role
Where is the problem? Why after "request.getPrincipal()" I get "SimplePrincipal"?
P.S. XXXXXX - our packages -
9. Re: getting Custom Principal in EJBContext.getCallerPrincipa
phantom Mar 2, 2004 1:10 PM (in response to nithila)"starksm" wrote:
Look at the jboss codebase for the org.jboss.security.auth.spiUsersRolesLoginModule and its base class org.jboss.security.auth.spi.UsernamePasswordLoginModule in the jboss-3.2/security/src/main tree for the commit behavior used with the example testcase. It will take 24 hours for this code to be available via anonymous cvs, try it at that time.
I tested new code from CVS (UsernameLoginModule). Principals in Subject are correct, but request.getPrincipal() return the same: SimplePrincipal:((
Please, help me.... -
10. Re: getting Custom Principal in EJBContext.getCallerPrincipa
starksm64 Mar 3, 2004 4:26 AM (in response to nithila)You have to provide your custom Principal as the "CallerPrincipal" binding in the Subject. The testcase for the custom principal uses a login config of:
<application-policy name = "jaas-test"> <authentication> <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> <module-option name = "unauthenticatedIdentity">anonymous</module-option> <module-option name = "principalClass">org.jboss.test.security.ejb.CustomPrincipalImpl</module-option> </login-module> </authentication> </application-policy>
a users.properties:scott=echoman stark=javaman jduke=theduke jdukeman=anotherduke invoker=invoker
a roles.properties:scott=Echo jduke=Echo jduke.CallerPrincipal=callerJduke jdukeman=Role2,Role3 jdukeman.CallerPrincipal=callerJdukeman
The login of jduke with the CallerPrincipal callerJduke will see a CustomPrincipalImpl -
11. Re: getting Custom Principal in EJBContext.getCallerPrincipa
tang Mar 3, 2004 9:47 AM (in response to nithila)I still doesn't work... Here is my code and all I did, this is only a test so my LoginModule is quite ridiculous...
First my LoginModule:
package securite;
import....
....
public class TestLoginModule extends UsernamePasswordLoginModule
{
private TestPrincipal caller;
public boolean login() throws LoginException {
if(super.login()) {
caller=new TestPrincipal(getUsername(),getUsersPassword(),"CallerPrincipal");
return true;
}
return false;
}
public boolean commit() throws LoginException {
if(subject != null)
{
Set principals = subject.getPrincipals();
if(principals != null)
{
principals.add((TestPrincipal) caller);
Group callerPrincipal = new SimpleGroup("CallerPrincipal");
callerPrincipal.addMember((TestPrincipal) caller);
principals.add(callerPrincipal);
// Set the roles for this principal in the 'Roles' group
Group group = getGroup(principals,"Roles");
group.addMember(new SimplePrincipal("JBossAdmin"));
principals.add(group);
return true;
}
}
return false;
}
private static SimpleGroup getGroup(Set principals, String groupName) {
Iterator it = principals.iterator();
while (it.hasNext()) {
java.security.Principal principal =
(java.security.Principal) it.next();
if (principal instanceof SimpleGroup
&& groupName.equals(principal.getName())) {
return (SimpleGroup) principal;
}
}
return new SimpleGroup(groupName);
}
//I don't use this method but I need it to extend UsernamePasswordLoginModule
protected Group[] getRoleSets() throws LoginException {
try {
String roles = "JBossAdmin";
Group[] groups = {new SimpleGroup("Roles")};
log.info("Getting roles for user="+getUsername());
SimplePrincipal role = new SimplePrincipal(roles);
log.info("Found role="+roles);
groups[0].addMember(role);
return groups;
}
catch(Exception e)
{
log.error("Failed to obtain groups for user="+getUsername(), e);
System.out.println("error");
throw new LoginException(e.toString());
}
}
//to login, the password just have to equals the username
protected String getUsersPassword()
{
String password = getUsername();
return password;
}
}
I have also written my Custom Principal called securite.TestPrincipal which is quite like simpleprincipal except the fact there is a name, a password and a comment in it.
I put all that in a library which I put in server/default/lib
Then I change the login-config.xml file adding:
<application-policy name = "essai">
<login-module code="securite.TestLoginModule"
flag = "required" >
<module-option name="principalClass">securite.TestPrincipal</module-option>
</login-module>
</application-policy>
I do my test using a Servlet. To access this servlet I have to login using the basic method. I configured the web.xml and jboss.xml so that the LoginModule used is mine. Then I use the HttpRequest.getUserPrincipal and I get a SimplePrincipal :(. This Servlet is also a client of an ejb which returns the CallerPrincipal (another SimplePrincipal...) and the Subject in order to check it was successfully filled. I also use your validateCallerPrincipal method.
I think that's all I do. Is there something I forgot to do? Did I make something wrong? This code is very simple, maybe too simple but I thought it would work. -
12. Re: getting Custom Principal in EJBContext.getCallerPrincipa
starksm64 Mar 3, 2004 12:48 PM (in response to nithila)You don't appear to be setting the groups correctly. This fixed version works fine with my ejb testcase:
package org.jboss.test.security.ejb; import java.security.acl.Group; import javax.security.auth.login.LoginException; import org.jboss.security.auth.spi.UsernamePasswordLoginModule; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; /** * @author Scott.Stark@jboss.org * @version $Revision:$ */ public class CustomPrincipalLoginModule extends UsernamePasswordLoginModule { private CustomPrincipalImpl caller; public boolean login() throws LoginException { if (super.login()) { caller = new CustomPrincipalImpl(getUsername()); return true; } return false; } protected Group[] getRoleSets() throws LoginException { try { // The declarative permissions Group roles = new SimpleGroup("Roles"); // The caller identity Group callerPrincipal = new SimpleGroup("CallerPrincipal"); Group[] groups = {roles, callerPrincipal}; log.info("Getting roles for user=" + getUsername()); // Add the Echo role roles.addMember(new SimplePrincipal("Echo")); // Add the custom principal for the caller callerPrincipal.addMember(caller); return groups; } catch (Exception e) { log.error("Failed to obtain groups for user=" + getUsername(), e); throw new LoginException(e.toString()); } } protected String getUsersPassword() { return "theduke"; } }
10:23:01,353 INFO [CustomPrincipalLoginModule] Getting roles for user=jduke
10:23:01,383 INFO [CustomPrincipalBean] validateCallerPrincipal, type=class org.jboss.test.security.ejb.CustomPrincipalImpl, loader=org.jboss.mx.loading.UnifiedClassLoader3@1280492{ url=file:/C:/cvs/JBoss3.2/jboss-3.2/build/output/jboss-3.2.4RC1/server/default/tmp/deploy/tmp54434security-jaas.jar,addedOrder=37}
10:23:01,383 INFO [CustomPrincipalBean] caller=jduke, class=class org.jboss.test.security.ejb.CustomPrincipalImpl -
13. Re: getting Custom Principal in EJBContext.getCallerPrincipa
starksm64 Mar 3, 2004 2:08 PM (in response to nithila)I added a test of getting the user principal from the web request and it did have a problem with returning the customer CallerPrincipal value. This has been fixed for the 3.2.4RC1 release.
The code changed was in the org.jboss.web.tomcat.security.JBossSecurityMgrRealm class. -
14. Re: getting Custom Principal in EJBContext.getCallerPrincipa
vitto Mar 24, 2005 9:41 AM (in response to nithila)I have the same problem.
I created my CustomLoginModule which implements LoginModule interface,
CustomPrincipal, CustomGroup (No JBoss Extention).public boolean commit() throws LoginException { this.userPrincipal = new CustomPrincipal("Username"); this.subject.getPrincipals().add(this.userPrincipal); CustomGroup group = new CustomGroup("Roles"); group.addMember(new CustomPrincipal("EmptyRole")); this.subject.getPrincipals().add(this.group); CustomGroup callerPrincipal = new CustomGroup("CallerPrincipal"); callerPrincipal.addMember(this.userPrincipal); this.subject.getPrincipals().add(callerPrincipal); }
When I called httpRequest.getUserPrincipal() on the Web, I got my CustomPrincipal.
When I called sessionContext.getCallerPrincipal() in the EJB, I got SimplePrincipal, but should my CustomPrincipal.
What is wrong????
Thanks.