classic "principal=null".
jkuhn Aug 21, 2003 3:54 PMHello,
I'm getting the classic "principal=null" exception. By doing a
search for "principal=null" in this forum, I've found 90 hits,
and have read them all. I feel like I know everything about JAAS,
except for the reason why my servlet will not create a bean.
I'm missing something, but I can't figure out what it is.
I'm attempting to use DatabaseServerLoginModule to log my users
into an application that is deployed in JBoss 3.2.1 (using Jetty)
1) Here is the code from my servlet:
************** servlet code -- START
String name = "jkuhn";
String passwordStr = "jkuhn";
char[] password = passwordStr.toCharArray();
LoginContext lc = null;
try{
AppCallbackHandler handler = new AppCallbackHandler(name, password);
lc = new LoginContext("toolkit", handler);
System.out.println("Created LoginContext");
lc.login();
System.out.println("Logged in.");
Iterator it = lc.getSubject().getPrincipals().iterator();
while(it.hasNext()) {
Object o = it.next();
System.out.println("principle: "+o.getClass().getName()+ " "+o);
}
}catch (LoginException le){
System.out.println("Login failed");
le.printStackTrace();
}
System.out.println("About to create CatalogManagementLocal"); // this line executes.
CatalogManagementLocal catalogManagement
= CatalogManagementUtil.getLocalHome().create();
System.out.println("Created CatalogManagementLocal"); // this line is never reached.
if (lc != null){
try{
lc.logout();
}catch(LoginException e){
System.out.println("Logout failed"+e);
}
}
************** servlet code -- END
2) The CallbackHandler is implemented as a static class inside the servlet
as follows:
************** callbackHandler (also in the servlet) -- START
static class AppCallbackHandler implements CallbackHandler {
private String username;
private char[] password;
public AppCallbackHandler(String username, char[] password){
this.username = username;
this.password = password;
}
public void handle(Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks instanceof NameCallback){
NameCallback nc = (NameCallback)callbacks;
nc.setName(username);
} else if (callbacks instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks;
pc.setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks, "Unrecognized Callback");
}
}
}
}
************** callbackHandler (also in the servlet) -- END
3) My login-config.xml is located in <JBOSS_HOME>/server/toolkit/conf/login-config.xml
It looks like this:
************** login-config.xml -- START
<application-policy name="toolkit">
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
flag="sufficient">
<module-option name="dsJndiName">java:/toolkitDS</module-option>
<module-option name="principalsQuery">select Password from Principals where PrincipalID=?</module-option>
<module-option name="rolesQuery">select Role, RoleGroup from Roles where PrincipalID=?</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.AnonLoginModule" flag="required">
<module-option name="unauthenticatedIdentity">guest</module-option>
</login-module>
</application-policy>
<!-- The security domain for the Postgres DB -->
<application-policy name = "PgDbRealm">
<login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule"
flag = "required">
<module-option name = "principal">user1</module-option>
<module-option name = "userName">user1</module-option>
<module-option name = "password">user1</module-option>
<module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=toolkitDS</module-option>
</login-module>
</application-policy>
************** login-config.xml -- END
NOTE: I have a fully functional schema in my postgres database
that allows logins under "user1" with password = "user1". And,
by accessing the database manually, I can verify that I have
populated tables called "principals" and "roles". In these tables,
there is user called "jkuhn" with a password of "jkuhn" and a role
of "Echo".
4) I have a descriptor for my session bean in the ejb-jar.xml file.
Plus, I've got what I believe are the neccessary assembly-descriptors
at the end of the file. Here are what they look like:
******** ejb-jar.xml (bean descriptor & assembly-descriptor) -- START
Stateless Session bean.
<ejb-name>CatalogManagement</ejb-name>
toolkit.admin.services.catalog.interfaces.CatalogManagementRemoteHome
toolkit.admin.services.catalog.interfaces.CatalogManagementRemote
<local-home>toolkit.admin.services.catalog.interfaces.CatalogManagementLocalHome</local-home>
toolkit.admin.services.catalog.interfaces.CatalogManagementLocal
<ejb-class>toolkit.admin.services.catalog.ejb.CatalogManagementSession</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref >
<res-ref-name>jdbc/toolkit</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<security-role-ref>
<role-name>EchoUser</role-name>
<role-link>Echo</role-link>
</security-role-ref>
<assembly-descriptor>
<security-role>
<role-name>Echo</role-name>
</security-role>
<method-permission>
<role-name>Echo</role-name>
<ejb-name>CatalogManagement</ejb-name>
<method-name>*</method-name>
</method-permission>
</assembly-descriptor>
******** ejb-jar.xml (bean descriptor & assembly-descriptor) -- END
5) I have added the following security-domain to the top
of my jboss.xml and jboss-web.xml file:
<security-domain>java:/jaas/toolkit</security-domain>
6) Here is the output when the servlet code is accessed:
************* JBoss Output snippet -- START
...
15:34:52,932 INFO [RequestProcessor] Processing a 'GET' for path '/admin/listCatalogItems'
15:34:53,025 INFO [ListCatalogItemsAction] execute()
15:34:53,025 INFO [STDOUT] Created LoginContext
15:34:53,057 INFO [STDOUT] Logged in.
15:34:53,072 INFO [STDOUT] principle: org.jboss.security.SimplePrincipal jkuhn
15:34:53,072 INFO [STDOUT] principle: org.jboss.security.NestableGroup Roles(members:Echo)
15:34:53,072 INFO [STDOUT] About to create CatalogManagementLocal
15:34:53,088 ERROR [SecurityInterceptor] Insufficient method permissions, principal=null, method=create, interface=LOCALHOME, requiredRoles=[Echo], principalRoles=[]
15:34:53,088 ERROR [LogInterceptor] EJBException, causedBy:
java.lang.SecurityException: Insufficient method permissions, principal=null, method=create, interface=LOCALHOME, requiredRoles=[Echo], principalRoles=[]
at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:214)
at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:81)
.......
************* JBoss Output snippet -- END
Notice that the login is successful. If you look at the JBoss output,
you can see that it says "Logged in." (as per the debug output).
Another reason that I know the login is successful, is that if I
remove the "jkuhn" user from the "principals" table in the database,
then the login fails.
So, I'm comfident that I've logged in. However, when execution is
attempted on the line of code that is a trying to "create()" an EJB,
I get the exception.
Can anybody tell me what I'm missing?
Thanks.