在 ContainerResponseFilter 的帮助下,我可以将 CORS 标头应用于所有传出响应,并且使用 ExceptionMapper,我可以对所有错误和异常执行相同的操作,except对于 Picketbox/Undertow 应该在 Wildfly 中抛出的任何与身份验证相关的异常。
我的异常映射器never无论我尝试什么,它都会捕获它,因此,前端无法读取 401 状态,因为响应没有附加 CORS 标头(XHR HTTP 状态代码变为 0)。
我在用this https://github.com/m9aertner/PBKDF2PBKDF2 设置为针对 MySQL 数据库进行身份验证,起初我认为可能由于身份验证是在单独的模块中运行,所以它没有被我的应用程序捕获,但即使在将所有身份验证代码移至我自己的应用程序中后,我也有同样的问题。
这是我尝试使用错误密码进行身份验证时得到的日志条目(当我根本不发送任何凭据时,我得到一个非常相似的日志条目):
2014-11-29 16:11:08,053 TRACE [org.jboss.security](默认任务4)PBOX000224:结束getAppConfigurationEntry(PBKDF2DatabaseDomain),AuthInfo:AppConfigurationEntry []:
[0]
LoginModule 类:com.example.myapplication.security.SaltedDatabaseServerLoginModule
ControlFlag: LoginModuleControlFlag: 必需
选项:
名称=dsJndiName,值=java:/用户
名称=principalsQuery,值=SELECTHash
FROM account
哪里 ID=?
名称=rolesQuery,值=SELECTRole
, '角色' 来自帐户 WHEREaccount
.ID
=?
2014-11-29 16:11:08,053 TRACE [org.jboss.security](默认任务4)PBOX000236:开始初始化方法
2014-11-29 16:11:08,053 TRACE [org.jboss.security](默认任务 4)PBOX000262:模块选项 [dsJndiName:java:/user,principalsQuery:SELECTHash
FROM account
WHERE ID=?, RolesQuery: SELECTRole
, '角色' 来自帐户 WHEREaccount
.ID
=?, suspendResume: true]
2014-11-29 16:11:08,053 TRACE [org.jboss.security](默认任务4)PBOX000240:开始登录方法
2014-11-29 16:11:08,053 TRACE [org.jboss.security] (默认任务 4)PBOX000263:执行查询 SELECTHash
FROM account
哪里 ID=?使用用户名[电子邮件受保护] /cdn-cgi/l/email-protection2014-11-29 16:11:08,062 DEBUG [org.jboss.security](默认任务 4)PBOX000283:用户名密码错误[电子邮件受保护] /cdn-cgi/l/email-protection2014-11-29 16:11:08,062 TRACE [org.jboss.security](默认任务 4)PBOX000244:开始中止方法
2014-11-29 16:11:08,062 DEBUG [org.jboss.security](默认任务4)PBOX000206:登录失败:javax.security.auth.login.FailedLoginException:PBOX000070:密码无效/需要密码
在 org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:284) [picketbox-4.0.21.Beta1.jar:4.0.21.Beta1]
在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)[rt.jar:1.8.0_25]
在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_25]
在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_25]
在 java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext.invoke(LoginContext.java:755) [rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext.access$000(LoginContext.java:195) [rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext$4.run(LoginContext.java:682) [rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext$4.run(LoginContext.java:680) [rt.jar:1.8.0_25]
在java.security.AccessController.doPrivileged(本机方法)[rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680) [rt.jar:1.8.0_25]
在 javax.security.auth.login.LoginContext.login(LoginContext.java:587) [rt.jar:1.8.0_25]
在 org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:408) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
在 org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:345) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
在 org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:333) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
在 org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:146) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
在 org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:111)
在 org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verify(JAASIdentityManagerImpl.java:82)
在 io.undertow.security.impl.BasicAuthenticationMechanism.authenticate(BasicAuthenticationMechanism.java:110) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:281) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:298) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:268) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:131) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:106) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:99) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:54) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:27) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
在 io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
在 java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
这是我的 ExceptionMapper 类(当前设置为捕获所有 Throwables,徒劳地尝试使其工作):
@Provider
public class NotAuthorizedExceptionMapper implements ExceptionMapper<Throwable>{
@Override
public Response toResponse(Throwable exception) {
Response response = Response.status(Response.Status.UNAUTHORIZED).build();
response.getHeaders().putSingle("Access-Control-Allow-Origin", "*");
response.getHeaders().putSingle("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, DELETE");
response.getHeaders().putSingle("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers, allow, content-length, date, last-modified");
return response;
}
我该怎么做才能捕获这些身份验证异常,从而将 CORS 附加到它们上?