Wildfly自定义登录模块错误

时间:2014-05-23 17:51:26

标签: jaas wildfly

我实现了一个通过Web服务访问的自定义loginModule,并检查JPA访问的数据库前面的用户名和密码。 我在jboss 7.1上运行它并且它工作正常,但在将它移动到Wildfly(并添加我认为正确的配置)后,我得到了一个源自wildfly类内部的NullPointerException。任何想法?

18:48:21,417 ERROR [io.undertow.request] (default task-3) UT005023: Exception handling request to /jass.ws/jaas/verifier/authenticateWithBasicUsernamePasswordAuth: java.lang.RuntimeException: java.lang.NullPointerException
    at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:126)
    at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verify(JAASIdentityManagerImpl.java:82)
    at io.undertow.security.impl.BasicAuthenticationMechanism.authenticate(BasicAuthenticationMechanism.java:110) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:281) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:298) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:268) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:131) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:106) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:99) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.handlers.AuthenticationCallHandler.handleRequest(AuthenticationCallHandler.java:50) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:687) [undertow-core-1.0.0.Final.jar:1.0.0.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_51]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_51]
    at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_51]
Caused by: java.lang.NullPointerException
    at org.wildfly.extension.undertow.security.AccountImpl.<init>(AccountImpl.java:61)
    at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:123)
... 29 more

这是我的自定义登录模块:

public class JPALoginModule implements LoginModule {

    CallbackHandler callbackHandler;
    Subject subject;
    Map sharedState;
    Map options;

    boolean success;

    LoginVerifier loginVerifier;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler,
        Map<String, ?> sharedState, Map<String, ?> options) {
        System.out.println("JPALoginModule.initialize()");
        this.callbackHandler = callbackHandler;
        this.subject = subject;
        this.sharedState = sharedState;
        this.options = options;
        InitialContext context = null;
        try {
            context = new InitialContext();
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            this.loginVerifier = (LoginVerifier) context.lookup("java:global/jaas.ear/jaas.ejb/LoginVerifierBean!beans.LoginVerifier");
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public boolean login() throws LoginException {
        System.out.println("JPALoginModule.login()");
        try {
            // Setup default callback handlers.
            Callback[] callbacks = new Callback[] {
                new NameCallback("Username: "),
                new PasswordCallback("Password: ", false) };

            callbackHandler.handle(callbacks);

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

            success = loginVerifier.verify(username, password);

            if (!success) {
                throw new LoginException(
                    "Authentication Failed: Wrong Password");
            } else if (success) {
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (UnsupportedCallbackException e) {
            e.printStackTrace();
        }
        catch (NullPointerException e) {
            System.out.println(e.getMessage()+" "+e.getLocalizedMessage());
        }
        return false;
    }

    @Override
    public boolean commit() throws LoginException {
        if (success) {
            if (subject.isReadOnly()) {
                throw new LoginException("subject is read only");
            }
            if (callbackHandler instanceof PassiveCallBackHandler) {
                ((PassiveCallBackHandler) callbackHandler).clearPassword();
            }
            return true;
        }
        else {
            return true;
        }
    }

    @Override
    public boolean abort() throws LoginException {
        logout();
        return true;
    }

    @Override
    public boolean logout() throws LoginException {
        if (callbackHandler instanceof PassiveCallBackHandler) {
            ((PassiveCallBackHandler) callbackHandler).clearPassword();
        }
        return true;
    }

我的jboss-web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <security-domain>java:/jaas/jpa-login-module</security-domain>
</jboss-web>

我的web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>jass.ws</display-name>
<security-constraint>
    <web-resource-collection>
        <web-resource-name></web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>jpa-login-module</realm-name>
</login-config>

和我的standalone.xml相关配置:

<security-domains>
     <security-domain name="jpa-login-module" cache-type="default">
         <authentication>
             <login-module code="com.jaas.JPALoginModule" flag="required"/>
         </authentication>
     </security-domain>
     <security-domain name="jpa-password-username" cache-type="default">
         <authentication>
             <login-module code="com.jaas.JPAUsernamePasswordLoginModule" flag="required"/>
         </authentication>
     </security-domain>
     <security-domain name="other" cache-type="default">
         <authentication>
             <login-module code="Remoting" flag="optional">
                 <module-option name="password-stacking" value="useFirstPass"/>
             </login-module>
             <login-module code="RealmDirect" flag="required">
                 <module-option name="password-stacking" value="useFirstPass"/>
             </login-module>
         </authentication>
     </security-domain>
     <security-domain name="jboss-web-policy" cache-type="default">
         <authorization>
             <policy-module code="Delegating" flag="required"/>
         </authorization>
     </security-domain>
     <security-domain name="jboss-ejb-policy" cache-type="default">
         <authorization>
             <policy-module code="Delegating" flag="required"/>
         </authorization>
     </security-domain>
</security-domains>

2 个答案:

答案 0 :(得分:4)

好的我找出了原因,因为我在验证后没有添加主体。

所以我补充说:

if (!success) {
    throw new LoginException(
        "Authentication Failed: Wrong Password");
} else if (success) {
    Principal passPrincipal = new UsernamePrincpal(username);
    subject.getPrincipals().add(passPrincipal);
    subject.getPrivateCredentials().add(password);
    return true;
}

并且有效

答案 1 :(得分:2)

NPE绝对是WildFly的Undertow扩展中的一个错误。我创建了一个新的JIRA - WFLY-3416

然而,为JBoss AS和Wildfly编写自定义登录模块的安全方法是将org.jboss.security.auth.spi.AbstractServerLoginModule子类化。

尝试类似:

import java.security.Principal;
import java.security.acl.Group;
import java.util.Map;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;

import org.jboss.security.auth.spi.AbstractServerLoginModule;

public class JPALoginModule extends AbstractServerLoginModule {

    LoginVerifier loginVerifier;
    java.security.Principal identity;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        System.out.println("JPALoginModule.initialize()");
        super.initialize(subject, callbackHandler, sharedState, options);
        InitialContext context = null;
        try {
            context = new InitialContext();
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            this.loginVerifier = (LoginVerifier) context
                    .lookup("java:global/jaas.ear/jaas.ejb/LoginVerifierBean!beans.LoginVerifier");
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public boolean login() throws LoginException {
        System.out.println("JPALoginModule.login()");
        try {
            // Setup default callback handlers.
            Callback[] callbacks = new Callback[] { new NameCallback("Username: "), new PasswordCallback("Password: ", false) };

            callbackHandler.handle(callbacks);

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

            if (!loginVerifier.verify(username, password)) {
                throw new LoginException("Authentication Failed: Wrong Password");
            }
            try {
                identity = createIdentity(username);
            } catch (Exception e) {
                throw new LoginException("Unable to Create Identity");
            }
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (UnsupportedCallbackException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            System.out.println(e.getMessage()+" "+e.getLocalizedMessage());
        }
        return false;
    }

    @Override
    public boolean commit() throws LoginException {
        if (identity != null) {
            if (subject.isReadOnly()) {
                throw new LoginException("subject is read only");
            }
            if (callbackHandler instanceof PassiveCallBackHandler) {
                ((PassiveCallBackHandler) callbackHandler).clearPassword();
            }
        }
        return super.commit();
    }

    @Override
    public boolean abort() throws LoginException {
        logout();
        return true;
    }

    @Override
    public boolean logout() throws LoginException {
        if (callbackHandler instanceof PassiveCallBackHandler) {
            ((PassiveCallBackHandler) callbackHandler).clearPassword();
        }
        return super.logout();
    }

    @Override
    protected Principal getIdentity() {
        return identity;
    }

    @Override
    protected Group[] getRoleSets() throws LoginException {
        return new Group[0];
    }
}

这将阻止NullPointerException,因为当用户成功通过身份验证时,会创建Principal实例(在identity成员变量中)。

相关问题