Glassfish V3 LDAP 身份验证失败不显示表单错误页面

Posted

技术标签:

【中文标题】Glassfish V3 LDAP 身份验证失败不显示表单错误页面【英文标题】:Glassfish V3 failed LDAP authentication does not display the form-error-page 【发布时间】:2012-01-06 10:40:59 【问题描述】:

我有一个声明了标准表单身份验证的 Web 应用程序,如下所示:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>ldap-realm</realm-name>
    <form-login-config>
     <form-login-page>/home</form-login-page>
     <form-error-page>/home?error=true</form-error-page> 
    </form-login-config>
</login-config>

我在 Glassfish 服务器中声明了 ldap-realm,以及连接到我的 LDAP 服务器所需的所有凭据。

问题是这样的:

在 Glassfish V2 上,如果我部署此应用程序,当尝试使用错误用户(或现有用户但密码错误)登录时,我会被重定向到 &lt;form-error-page&gt; (/home?error=true) 中声明的 URL 和此页面显示用户友好的错误消息,例如“您无法验证 bla bla”。此外,如果此时查看日志,我会看到一条 WARN 消息,告诉我用户输入的凭据无法针对 LDAP 服务器进行身份验证。

在 Glassfish V3(在 3.0 和 3.1 上都尝试过)上,当我部署完全相同的应用程序并在 GF 中配置完全相同的 ldap-realm 时,当用户尝试使用正确的凭据进行身份验证时一切正常,但是当他输入错误用户或正确用户/错误密码我收到 404 页面未找到错误,而不是从 &lt;form-error-page&gt; 重定向到 URL。更重要的是,发生的情况是,在验证无效时,用户会看到我为 404 错误声明的 html 页面,而不是 form-error-page。同样在 glassfish 日志中,我现在有一个异常堆栈跟踪,如下所示:

[#|2012-01-05T16:49:28.878+0100|WARNING|glassfish3.1|javax.enterprise.system.container.web.com.sun.web.security|_ThreadID=130;_ThreadName=Thread-1;|Exception
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Failed file login for aaaa.
        at com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:394)
        at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:240)
        at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:153)
        at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:483)
        at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:425)
        at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:269)
        at org.apache.catalina.authenticator.AuthenticatorBase.processSecurityCheck(AuthenticatorBase.java:909)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:546)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:623)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
        at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
        at java.lang.Thread.run(Thread.java:662)
Caused by: javax.security.auth.login.LoginException: Failed file login for aaaa.
        at com.sun.enterprise.security.auth.login.FileLoginModule.authenticate(FileLoginModule.java:84)
        at com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:117)
        at com.sun.appserv.security.AppservPasswordLoginModule.login(AppservPasswordLoginModule.java:148)
        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 com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:382)

老实说,我很困惑。 ldap-realm 定义正确,因为 VALID 身份验证可以正常工作。表单错误页面的 URL 也是有效的,因为如果我在地址栏中手动输入它,我会得到身份验证错误页面。我唯一想做的就是制作一个自定义的 LdapRealm 实现,并且在身份验证失败时不再抛出该异常。但这不是很酷。

我的问题是,有谁知道 Glassfish V2 和 V3 处理失败身份验证的方式是否有所不同? Glassfish V3 是否有一些额外的配置参数可用,使其在用户身份验证无效时返回表单错误页面,而不是抛出异常并返回 404?

【问题讨论】:

【参考方案1】:

嗯,没有人回答,我找到了一种解决方法,虽然不是一个好的方法。如问题中所述,我将&lt;form-error-page&gt; 的url 声明为servlet,并且从未在GF3 中显示。我所做的就是将该 url 替换为指向静态文件(如 /loginError.html)的 URL,并在该静态页面中重定向到所需的 url(处理登录错误的 servlet 的那个)。这样我就得到了想要的行为。

【讨论】:

以上是关于Glassfish V3 LDAP 身份验证失败不显示表单错误页面的主要内容,如果未能解决你的问题,请参考以下文章

Zeppelin - LDAP 身份验证失败

Spring boot Ldap 身份验证失败,LDAP 错误代码 49 - 80090308 数据 52e

Azure 应用服务中的 LDAP 身份验证失败

Hive 中的 Ldap 身份验证用户过滤器:失败

Ldap 用户授权失败 - 未处理的 Spring 身份验证“访问被拒绝”

针对 ldap 的 Apache2 身份验证因“找不到用户”而失败