I am experimenting with JAAS on Tomcat 7.0.30 and am trying to use
JAASMemoryLoginModule as a simple test. Unfortunately, I am getting a
null pointer exception when I try to login to my web application.
My tomcat-users.xml file is basically equivalent to:
<tomcat-users>
<role rolename="role1"/>
<role rolename="role2"/>
<user username="user1" password="password1" roles="role1"/>
<user username="user2" password="password2" roles="role1, role2"/>
</tomcat-users>
My jaas.config file is trivial as well:
Catalina {
org.apache.catalina.realm.JAASMemoryLoginModule REQUIRED debug=true;
};
My realm element is nested inside an engine element in server.xml:
<Realm className="org.apache.catalina.realm.JAASRealm"
userClassNames="org.apache.catalina.realm.GenericPrincipal"
roleClassNames="org.apache.catalina.realm.GenericPrincipal"/>
The stack trace for my exception is as follows:
java.lang.NullPointerException
at java.lang.String.compareTo(String.java:1167)
at java.lang.String.compareTo(String.java:92)
at java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.sort(Arrays.java:1079)
at
org.apache.catalina.realm.GenericPrincipal.<init>(GenericPrincipal.java:134)
at
org.apache.catalina.realm.GenericPrincipal.<init>(GenericPrincipal.java:106)
at
org.apache.catalina.realm.JAASRealm.createPrincipal(JAASRealm.java:556)
at
org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:441)
at
org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:332)
at
org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
This exception is occurring when we are trying to construct a new
GenericPrincipal instance at the end of the createPrincipal method in
the org.apache.catalina.realm.JAASRealm class.
// Return the resulting Principal for our authenticated user
return new GenericPrincipal(username, null, roles, userPrincipal,
loginContext);
The "roles" argument is a list of Strings taken from the names of role
principals, as shown in this snippet from the same method:
if (roleClasses.contains(principalClass)) {
roles.add(principal.getName());
if( log.isDebugEnabled() ) {
log.debug(sm.getString("jaasRealm.rolePrincipalAdd",
principal.getName()));
}
}
The problem is that in the commit method of the
org.apache.catalina.realm.JAASMemoryLoginModule class, role principals
are added to the subject with the name set to null, as shown below
(note: the first argument to the GenericPrincipal constructor is the name).
public boolean commit() throws LoginException {
log.debug("commit " + principal);
// If authentication was not successful, just return false
if (principal == null)
return (false);
// Add our Principal to the Subject if needed
if (!subject.getPrincipals().contains(principal)) {
subject.getPrincipals().add(principal);
// Add the roles as additional subjects as per the contract
with the JAASRealm
if (principal instanceof GenericPrincipal) {
String roles[] = ((GenericPrincipal) principal).getRoles();
for (int i = 0; i < roles.length; i++) {
// ********** Here is the line that I think may be
wrong ***********
subject.getPrincipals().add(new
GenericPrincipal(null, roles[i], null));
}
}
}
committed = true;
return (true);
}
As a result, the "roles" list in the createPrincipal method in the
org.apache.catalina.realm.JAASRealm class (see above) contains a number
of null Strings, which leads to a null pointer exception in the
GenericPrincipal constructor, when it calls Arrays.sort, as shown below.
public GenericPrincipal(String name, String password, List<String>
roles, Principal userPrincipal, LoginContext loginContext) {
super();
this.name = name;
this.password = password;
this.userPrincipal = userPrincipal;
if (roles != null) {
this.roles = new String[roles.size()];
this.roles = roles.toArray(this.roles);
if (this.roles.length > 0)
Arrays.sort(this.roles);
}
this.loginContext = loginContext;
}
This seems like it could be a bug, but given that I am new to JAAS on
Tomcat, I may just be doing something wrong. Any JAAS/Tomcat experts out
there able to point me in the right direction?
Jim Doble
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org