4

我有一个 JAAS 项目,它由 RolePrincipal.java、UserPrincipal.java 和 JaasLoginModule.java 组成,如本问题底部所示。该项目已运行Tomcat 6并在 META-INF 文件夹中配置 Realm,context.xml如下所示:

<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm" 
            appName="JaasLoginModule"
            userClassNames="org.huahsin.RolePrincipal"
            roleClassNames="org.huahsin.UserPrincipal"/>
</Context>

为了运行这个项目,我需要一个这样的 jaas.conf:

JaasLoginModule {
    org.huahsin.JaasLoginModule required debug=true;
};

从 Eclipse 启动 Tomcat 时,将项目工作区和以下行放入 JVM 参数中:

-Djava.security.auth.login.config="/home/huahsin/workspace/Jaas4/jaas.config"

现在,当我执行此操作时,我的控制台中显示以下错误:

WARNING: Login exception authenticating username "user123"
javax.security.auth.login.LoginException: Security Exception
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:856)
    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:580)
    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:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.SecurityException
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:857)
    ... 17 more

奇怪的是身份验证已通过login()但未能subject.getPrincipals().add(userPrincipal);在 JaasLoginModule.java 中进行。我不知道如何继续处理这个问题?


角色主体.java

public class RolePrincipal implements Principal {

    private String name;

    public RolePrincipal(String name) {
        super();
        this.name = name;
    }

    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

用户主体.java

public class UserPrincipal implements Principal {

    private String name;

    public UserPrincipal(String name) {
        super();
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

JaasLoginModule.java

public class JaasLoginModule implements LoginModule {

    private CallbackHandler handler;

    private Subject subject;

    private String loginName;

    private List<String> userGroups;

    private UserPrincipal userPrincipal;

    private RolePrincipal rolePrincipal;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
            Map<String, ?> sharedState, Map<String, ?> options) {

        handler = callbackHandler;
        this.subject = subject;
    }

    @Override
    public boolean login() throws LoginException {

        Callback[] callbacks = new Callback[2];
        callbacks[0] = new NameCallback("User Name:");
        callbacks[1] = new PasswordCallback("Password:", true);

        try {
            handler.handle(callbacks);

            String username = ((NameCallback) callbacks[0]).getName();
            String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());

            if( username != null && username.equals("user123") &&
                    password != null && password.equals("pass123") ) {

                loginName = username;
                userGroups = new ArrayList<String>();
                userGroups.add("admin");

                return true;
            }

            throw new LoginException("Authentication Failed.");
        }
        catch( IOException e ) {
            throw new LoginException(e.getMessage());
        }
        catch( UnsupportedCallbackException e ) {
            throw new LoginException(e.getMessage());
        }
    }

    @Override
    public boolean commit() throws LoginException {

        userPrincipal = new UserPrincipal(loginName);
        subject.getPrincipals().add(userPrincipal);

        if( userGroups != null && userGroups.size() > 0 ) {
            for( String groupName : userGroups ) {
                rolePrincipal = new RolePrincipal(groupName);
                subject.getPrincipals().add(rolePrincipal);
            }
        }

        return true;
    }

    @Override
    public boolean abort() throws LoginException {

        return false;
    }

    @Override
    public boolean logout() throws LoginException {

        subject.getPrincipals().remove(rolePrincipal);
        subject.getPrincipals().remove(userPrincipal);

        return true;
    }

}

web.xml

<web-app ...>
  <security-constraint>
    <web-resource-collection>
        <web-resource-name>Admin</web-resource-name>
        <url-pattern>/admin/*</url-pattern>
    </web-resource-collection>

    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
  </security-constraint>

  <security-role>
    <role-name>admin</role-name>
  </security-role>

  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Admin Realm</realm-name>
  </login-config>
</web-app>
4

0 回答 0