JavaEE身份验证错误处理

JavaEE身份验证错误处理,java,security,authentication,jakarta-ee,Java,Security,Authentication,Jakarta Ee,我们目前正在尝试在WebSphere6.1Web容器内实现一个web应用程序,该应用程序使用JavaEE身份验证机制,并使用基于表单的登录。如果认证成功,我们就一切正常;正在检索LDAP成员资格组,正在执行组到角色的映射,并且角色正在返回给web应用程序并由web应用程序正确解释 如果身份验证未成功,将返回表单登录错误页面。然而,这是一个静态页面,只是简单地说“有一个错误”。我们如何捕获阻止成功登录的特定错误(用户名/密码不正确、LDAP存储库不可用、帐户锁定、密码过期等)?似乎应该有一些简单的

我们目前正在尝试在WebSphere6.1Web容器内实现一个web应用程序,该应用程序使用JavaEE身份验证机制,并使用基于表单的登录。如果认证成功,我们就一切正常;正在检索LDAP成员资格组,正在执行组到角色的映射,并且角色正在返回给web应用程序并由web应用程序正确解释


如果身份验证未成功,将返回表单登录错误页面。然而,这是一个静态页面,只是简单地说“有一个错误”。我们如何捕获阻止成功登录的特定错误(用户名/密码不正确、LDAP存储库不可用、帐户锁定、密码过期等)?似乎应该有一些简单的方法来做到这一点,因为您希望以不同的方式处理一些“安全”异常。

这是一个古老的知识-我相信已经用tomcat做了这样的事情。据我所知,没有标准的方法,因为实现与请求和前端web内容完全分离,因此很难在验证组件和前端之间建立任何通信方式(例如错误页面)


我们最终采用了一种特定于tomcat的方法,在很大程度上依赖于当前的实现。我已经不在那家公司工作了,所以我无法说出代码的当前状态或我们当时选择的解决方案。我相信您还必须有一些特定于Websphere的解决方案—可以使用线程局部变量,使用试图登录的用户名键入消息,以某种方式获取会话标识符或类似内容。

查看本文。我相信它涵盖了您能够传递身份验证错误原因的要求。

我使用Struts,因此它将为您进行转发。如果你没有一个框架(为什么不呢?),你将不得不手工操作

JavaEE规范涵盖了j_安全检查servlet

登录页面将j_用户名和j_密码发布到j_安全检查servlet。您的应用程序将被配置为错误访问未经授权的页面(参见web.xml),但(最初)将调用servlet。401或403将转到禁止页面(同样是web.xml)

在这个servlet(扩展了HttpServlet)中,您将检查所有这些好东西

public final void doGet(javax.servlet.http.HttpServletRequest request,
    javax.servlet.http.HttpServletResponse response)
    throws javax.servlet.ServletException, java.io.IOException
{
    // initialize the app
    AppInit initializer = new AppInit();

    // get the logger
    log = new Log4jWrapper(this.getClass());

    // initialize the application session
    HttpSession sess = request.getSession(true);
    sess.setAttribute(CommonConstants.SESSION_CURR_USER_ID, request.getRemoteUser());

    // initialize the JSP to forward to based on the user role
    String fwdJSP = "SetupMainPage.jsp";
    if (request.isUserInRole(CommonConstants.ROLE_MANAGER)) {
        log.debug("User is a Manager");
    }
    //else other role checks - (these are users in groups in the LDAP)
    // initialize the application session and set a variable to indicate that
    // we are coming from a first time login (not a timeout login)
    sess.setAttribute(CommonConstants.SESSION_COMING_FROM_INITIAL_LOGIN,"TRUE");
    disp = getServletContext().getRequestDispatcher("SetupMainPage.jsp");
    disp.forward(request, response);
}
//else failure
未知用户

[11/22/08 8:54:47:993 EST]7f6ac69c FormLoginServ E SECJ0118E:用户身份验证过程中的身份验证错误

正确的用户-错误的密码,但request.getRemoteUser()将有一个值

[11/22/08 8:56:45:082 EST]7f51469c FormLoginServ E SECJ0118E:对用户jbsymolo进行身份验证时出现身份验证错误

不幸的是,我没有任何人被锁定的例子,但我将假设主安全目录(LDAP)将为该用户提供一个条目

这是别人写的(所以我不能相信)

我认为这描述了如何做你想做的事情

特别是如何从任意底层身份验证源检索身份验证异常(看起来像Websphere将其称为用户注册表)

Throwable t=com.ibm.websphere.security.auth.WSSubject.getRootLoginException()
如果(t!=null)
t=确定原因(t)

其中determineCause()在同一页上定义。这样,即使您的服务器配置为针对John Deer拖拉机进行身份验证,您也可以访问“OutOfGasLoginException”(如果有)。上述代码可以进入容器重定向到的Servlet、Servlet过滤器或JSP(如jsymolon所述)。它只检查异常,然后在结果页面上放置相应的友好错误消息。

JavaEE规范没有提供获取身份验证反馈(如错误代码)的标准方法

根据第57页的以下灰色注释:IBM特定扩展可用,因此错误页面JSP可以根据错误状态代码报告特定消息(如密码过期)

根据您的WebSphere安装中TechSamp包中的FormLoginWeb示例(
samples/src/TechSamp/FormLoginWeb
)应该演示这种IBM特定的扩展,但是。。。唯一有趣的是
LoginFilter
,它拦截对
/j_security_check
的调用,并能够执行登录前验证和登录后操作,如中所述


使用这种机制,可以从JAAS主题获取登录异常,并在HttpSession中设置登录错误代码,以便错误页面可以生成特定消息。

这篇文章不错,但我读到了“如何在身份验证期间向用户反馈错误”的问题。身份验证(在JEE中)与应用程序分离,因此过滤器无法拦截用于登录的请求(以及用户名/密码)。这通常是很好的,除了在这样的情况下…有趣的是,我从来没有尝试过实现我自己的j_安全检查servlet。我一直认为容器会处理这个问题,而应用程序将没有机会看到密码。我会马上查的…抱歉-这有点误导。您不必实现自己的j_security_check servlet,因为它是由Websphere处理的。使用上面的代码检查servlet的结果并采取行动。“JavaEE规范没有提供标准的方法来获得错误代码之类的身份验证反馈”这是怎么回事?这个API提供了一种将您自己的特定身份验证机制插入JavaEE容器的方法。如果希望从供应商提供的LDAP身份验证实现中获得反馈,则必须在其周围创建一个包装器,以便从应用程序代码中访问身份验证失败的详细信息。不,没有JavaEE规范