繁体   English   中英

记住我,使用JSF + JAAS自动登录

[英]Remember me auto login with JSF + JAAS

我试图在我的应用程序中添加记住我的功能,但是由于某种原因HttpServletRequest.login()抛出ServletException

javax.servlet.ServletException: Login failed
at com.cleanup.filter.AutoLoginFilter.doFilter(AutoLoginFilter.java:71)

第71行:

req.login(adminUser.getEmail(), adminUser.getPwd());

我知道根据文档:

抛出 :ServletException-如果配置的登录机制不支持用户名密码身份验证,或者已经建立了非空的调用者身份(在登录之前),或者对提供的用户名和密码的验证失败。

这又意味着凭据是“无效的”,这是正确的,因为登录机制可以正常工作。

但是,为什么会引发此异常呢?

我的理论是,由于password已加密,因此,如果是这种情况,则request.login(..,..)也可以使用已散列的密码?

这是我的过滤器:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {


    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;

    String remoteUser = (String) req.getRemoteUser();

    if (remoteUser == null) {

        String uuid = CookieRememberUtil.getCookieValue(req);

        System.out.println("Found cookie" + uuid);

        if (uuid != null) {
            AdminUsers adminUser = cookiesFacade.getAdminUserFromUUID(uuid);

            if (adminUser != null) {

                req.login(adminUser.getEmail(), adminUser.getPwd());
                CookieRememberUtil.addCookie(resp, uuid);
            } else {
                CookieRememberUtil.removeCookie(resp);
            }
        }

    }
    chain.doFilter(request, response);

}

问题是备份登录过程的基础领域实现。

登录方法不可避免地要遵循配置的Realm进行实际身份验证。 例如,如果您使用的是数据库领域,则领域将在数据库中查找用户,比较密码,然后提取角色信息。

因此,您需要做的是使Realm具有“ cookie意识”。

也就是说,当您点击过滤器时,您可以检查“记住我” cookie,并将该信息基本上传递给登录方法,以便最终到达您的自定义领域,然后做正确的事情。

String uuid = CookieRememberUtil.getCookieValue(req);
if (uuid != null) {
    req.login("***REMEMBER_ME***", uuid);
} else {
    ... run your normal login logic
}

然后,领域将查找魔术用户,其名称为“ REMEMBER_ME ”,并使用UUID提取凭据,并建立主体。

然后,通常,您不允许用户名中带有“ *”之类的内容,这样一来,某人登录并向您发送带有UUID的垃圾邮件就很难获得访问权限。 您可以在登录时进行检查,并使用无效的用户名,找不到的用户等直接终止。

因此,TLDR,您需要为容器定义一个自定义领域。

编辑:

为了使容器执行授权,它使用一种称为领域的概念。 领域是用于验证用户,检查其密码并通过创建主体来加载其角色的一段代码。 所有的容器都带有内置的Realms,它们执行基本的工作:处理平面文件,处理数据库,也许处理LDAP服务器。

您可以编写一个自定义的Realm实现并将其安装在您的容器中,它通常是您实现的非常简单的接口。

领域的整个目的是获取凭据,并返回一个主体。 使用Servlet 3.x的程序化登录功能,您不仅可以选择何时进行登录调用,还可以选择要传递到Realm的凭据。

通常,您输入用户名和密码。 Realm查找用户名,对密码进行哈希处理,将其与存储的内容进行比较,然后瞧瞧,创建一个简单的Principal并将其返回。

在您的情况下,当您设置了REMEMBER_ME cookie时,您将返回cookie或可从中提取的数据,而不是返回用户名和密码(因为您没有提示输入用户名和密码,而没有用户名和密码)。曲奇饼。 但是,您唯一的登录界面(通过登录方法)接受用户名和密码。 实际上,它接受两个字符串,可以将其用作用户名和密码。 实际上,它们可以是任意值-例如一个标志,指示Realm通过cookie值以及相关的cookie值登录。

领域使用cookie值来查找标识,并创建适当的主体。 您返回的主体不必具有与登录函数的第一个参数相同的“用户名”,它可以返回所需的任何主体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM