Question

I followed this tutorial to learn JAAS. That example worked for me, so I created my own version (I'm using Tomcat 6 and Java 6), but I can not get it to work (exception on the bottom of the post).

(I can't put online the sources in a ZIP because the proxy. Sorry.)

This is the JAAS:

TestJAAS {
    test.auth.MyModule required debug=true;
};

This is the user Principal:

public class MyUser implements Principal {

    private String name;

    public MyUser(String name) {
         super();
         this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
}

This is the role Principal:

public final class MyRole implements Principal {

    public String getName() {
         return "Superman";
    }
}

This is the login module:

public class MyModule implements LoginModule {

    private CallbackHandler handler;
    private Subject subject;
    private MyUser user;
    private final MyRole ROLE = new MyRole();

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
            Map<String, ?> sharedState, Map<String, ?> options) {
        this.handler = callbackHandler;
        this.subject = subject;
    }
    public boolean login() throws LoginException {
        NameCallback nc = new NameCallback("login");
        PasswordCallback pc = new PasswordCallback("password", false);

        String name = nc.getName();
        String pass = String.valueOf(pc.getPassword());

        try {
            handler.handle(new Callback[]{nc, pc});
        } catch (Exception ex) {
            throw new LoginException(ex.getMessage());
        }

        if ("123".equals(name) && "secret".equals(pass)) {
            user = new MyUser(name);
            return true;
        }

        throw new LoginException();
    }
    public boolean commit() throws LoginException {
        subject.getPrincipals().add(user);
        subject.getPrincipals().add(ROLE);
        return true;
    }
    public boolean abort() throws LoginException {
        return false;
    }
    public boolean logout() throws LoginException {
        subject.getPrincipals().remove(user);
        subject.getPrincipals().remove(ROLE);
        return true;
    }

}

This is the context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm" appName="TestJAAS"
        userClassNames="test.auth.MyUser" roleClassNames="test.auth.MyRole" />
</Context>

And this is the web.xml:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>MyProtectedResources</web-resource-name>
        <url-pattern>/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>Superman</role-name>
    </auth-constraint>
</security-constraint>
<security-role>
    <role-name>Superman</role-name>
</security-role>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>MyProtectedResources</realm-name>
</login-config>

And this is the exception when I try to log in on http://localhost:8080/TestJAAS/admin/admin.html:

5-dic-2013 10.07.29 org.apache.catalina.realm.JAASRealm authenticate
AVVERTENZA: Login exception authenticating username "123"
javax.security.auth.login.LoginException: java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at test.auth.MyModule.login(MyModule.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:409)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:334)
    at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:181)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:872)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:409)
    at org.apache.catalina.realm.JAASRealm.authenticate(JAASRealm.java:334)
    at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:181)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:528)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

The config file is loaded correctly. Why my username and password are null? Thanks in advance.

Was it helpful?

Solution

You have at least one error, located in this code:

    String name = nc.getName();
    String pass = String.valueOf(pc.getPassword());

    try {
        handler.handle(new Callback[]{nc, pc});
    } catch (Exception ex) {
        throw new LoginException(ex.getMessage());
    }

You read the name/password from the callbacks, before they are filled by the callback handler!!!

You will need to put the String name=...;String pass=... part after handler.handle(...). The example you linked does this too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top