我实现了一个通过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>
答案 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
成员变量中)。