3

如何通过 JSF 操作(或在 servlet doGet/doPost方法中)对用户进行身份验证?我的意思是:

Authenticator auth = ...;
if (!auth.authenticate("user","password"))
{
    FacesContext.getInstance().addMessage("Incorrect username or password", null);
}

限制:

  • 此方法必须与容器管理的安全性兼容。(即 `HttpServletRequest.getRemoteUser()` 必须返回经过身份验证的用户)
  • 这种方法必须在任何地方都有效(即在每个应用服务器上)。

未使用j_security_check或其他 J2EE 身份验证类型(BASIC、DIGEST 等...)

有可能的?
或者如何以这种方式创建验证码?
验证登录名和密码不为空?
当然,在单页上并且没有 JavaScript...

类似的问题......但没有回答这个问题:

JSF 身份验证和授权
在 Java EE / JSF 中使用 j_security_check 执行用户身份验证

编辑 1
我的意思是 serlvet API 至少 2.3。是的,我在 Servlet API 3.0 中读到过login,但它仅受新版本的应用程序服务器支持。

我认为这里可以是一些为每个应用程序服务器实现此身份验证的解决方案。有时通过一些技巧,有时通过为此目的设计的特殊类。像这样:

private Class<?> tryClass(String name)
{
    try
    {
        return Class.forName(name);
    }
    catch (ClassNotFoundException e)
    {
        return null;
    }
}

public boolean authenticate(String username, String password) throws AuthenticationException
{
    try
    {

        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        Object request = context.getRequest();
        Object response = context.getResponse();

        Class<?> authClass = tryClass("com.sun.appserv.security.ProgrammaticLogin");
        if (authClass != null)
        {
            return (Boolean)authClass.getMethod("login").invoke(
                authClass.newInstance(), "user", "password", request, response);
        }

        authClass = tryClass("org.jboss.web.tomcat.security.login.WebAuthentication");
        if (authClass != null)
        {
            return (Boolean)authClass.getMethod("login").invoke(
                authClass.newInstance(), "user", "password");
        }

        // ... other hacks ...application servers 

    }
    catch (Exception e)
    {
        throw new AuthenticationException("an error occured during user authentication", e);
    }

    return false;
}
4

2 回答 2

1

程序化登录非常棘手,并且似乎因应用程序服务器而异。我相信使用 j_security_check 是最成功的,它将允许您的应用程序跨各种应用程序服务器工作。

困难的部分是让应用程序服务器接受身份验证。在 Tomcat 上,我已经能够执行myLoginModule .login() 并让登录模块成功,但用户未通过容器进行身份验证。JBoss 有一些代码可以让编程身份验证在 JBoss 和 Tomcat 之间工作(因为 Tomcat 位于 JBoss 中)。为 Glassfish 研究这一点,我得到的印象是程序化登录非常困难,应该留给专业人士。

Glassfish 文档 (http://docs.sun.com/app/docs/doc/820-4496/beacm?a=view) 说:

程序化登录特定于企业服务器,不能移植到其他应用程序服务器。

编辑

j_security_check 方法需要一点时间来适应,但是一旦你学会了解决它,就会非常成功。基本上,您可以有一个欢迎页面,将用户重定向到您的应用程序;如果用户尚未登录,他们将被发送到您的登录页面。您的登录页面可以是您网站的主页。进入主页后,用户可以导航到您网站的其他“不安全”页面。如果您愿意,您也可以在这些页面上包含登录表单。您不会被单一的登录页面所困。

编辑 2

我一直在使用 AJAX(通过 Richfaces)检查用户的用户名/密码,并在需要时显示错误消息。如果凭据正确,则提交指向 j_security_check 的表单以进行实际身份验证。

编辑 3

BalusC 在第二个链接问题 (http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee-6-using-jsf-2-0) 上建议的编程登录方法正在做request.login(...)看起来很棒。我很快就会尝试;o) Glassfish 3 支持 Servlet 3,但还没有其他支持(将成为 Tomcat 7 的一部分,可能是 JBoss 6)。

于 2010-11-17T18:20:06.330 回答
1

啊,它是J2EE 1.3 Java EE 5。太糟糕了,每当你想继续使用容器管理的安全性时,你就很不走运。您必须从幕后获取特定于容器的实现。顺便说一句,“没有j_security_checkBASIC/DIGEST 的容器管理安全”是自相矛盾的。我个人会忘记这一切并自行开发安全性或获取更具可配置性的 3rd 方实现,例如Spring Security

于 2010-11-17T21:00:42.817 回答