2017-02-17 71 views
0

我想补充记得我功能,我的应用程序,但由于某些原因,HttpServletRequest.login()抛出一个ServletException记住我自动登录与JSF + JAAS

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); 

} 

回答

0

的问题是,备份您的登录过程的基本境界的实现。

登录方法不可避免地会根据配置的Realm来执行该实际身份验证。例如,如果您使用的是DB 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向您发送垃圾邮件以尝试获取访问权限。您在登录时检查并简单地以无效用户名,用户未找到等中止。

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

编辑:

为了使容器执行授权时,它使用一个概念称为境界。Realm是验证用户的一段代码,检查他们的密码并通过创建一个Principal来加载他们的角色。所有的容器都带有内置的领域,这些领域可以做一些基本的事情:针对平面文件工作,针对数据库工作,可能针对LDAP服务器。

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

领域的全部目的是取得凭据,并返回一个委托人。使用Servlet 3.x的程序化登录工具,您不仅可以选择何时进行登录调用,还可以选择将什么凭证传递给Realm。

通常,您传递用户名和密码。 Realm查找用户名,哈希密码,将它与商店进行比较,然后创建一个简单的Principal并返回它。

在你的情况下,当你设置了REMEMBER_ME cookie,而不是返回用户名和密码(你没有,因为你没有提示),你返回的cookie或数据可以从cookie中提取。但是,通过登录方法,您与Realm的唯一接口将接受用户名和密码。实际上,它接受两个字符串,它们可以是一个用户名和密码。实际上,它们可以是任何 - 例如标志告诉Realm通过cookie值登录,以及关联的cookie值。

The Realm使用cookie值查找标识并创建适当的Principal。您返回的委托人不必具有与登录功能的第一个参数相同的“用户名”,它可以返回任何它想要的委托人。

+0

不知道我理解你。 – shep