3

我有一个 JSF Web 应用程序,它使用 cookie 进行自动身份验证,而不提示输入用户名和密码。它使用带有用户名和随机 UUID 的 cookie,并使用 aWebFilter进行重定向。

当客户端没有 cookie 时,通过HttpServletRequest #login(String username, String password)完成身份验证。在幕后,这种方法使用 JAAS 身份验证,并LDAP在后面使用服务器。

当我的应用程序通过保存用户 ID 和 UUID 的 cookie 识别用户时,我的问题就出现了。在这个情况下,

  1. 应用程序不知道密码,因此HttpServletRequest #login(String username, String password)无法使用该方法。
  2. 我应该通过 JNDI 向 LDAP 服务器询问密码吗?乍一看,这似乎是不可能的
  3. 或者,我可以将密码存储在我的数据库中。但这意味着信息的重复,我不喜欢这样。
  4. 我见过周围的人只是将属性“角色”设置为会话,但这似乎并不等同于 JAAS 登录。“等效”是指能够使用isUserInRole()getUserPrincipal()方法。

所以,问题是:在这种情况下我应该如何登录用户?我希望这个问题现在更清楚了。

编辑

为了让代码说话,我添加了一个简化版的 Managed Bean:

@ManagedBean
@SessionScoped 
public class loginBean() {
    private String username = null;
    private String password = null;
    private UUID uuid = null;
    private boolean rememberMe = false;

    public void doLogin() {
        checkCookies();   // this method sets the property values after checking if 
                          // username & uuid match the ones saved previously
        if (username != null && uuid != null && rememberMe) {
            // authenticate automatically. Here I don't know how to proceed, because 
            // I don't have the password, unless I have saved it in the application's db,
            // duplicating it because it's already in LDAP server.
        } else {
            httpServletRequest.login(username, password);  // this uses LDAP behind JAAS
            createCookies();  // this method also saves username & uuid in the app's db
        }
    }
4

2 回答 2

3

要以自定义方式(在您的情况下通过 cookie 和 UUID 而不是密码)进行实际容器登录,您需要创建自己的登录模块。

Java EE 中用于此的专用 API 是 JASPI/JASPIC(人们永远无法完全同意名称,例如 google 查询变得复杂)。

登录模块处于完全控制之下,并且不必通过 ldap 服务器进行身份验证(如果您的应用程序可以在本地验证 cookie 有效 100%)。您可能确实必须授权用户(向 ldap 服务器询问用户拥有的角色/组)。

作为 JASPI/JASPIC 的替代方案,您还可以查看服务器正在使用的专有登录模块机制。

于 2012-08-13T09:08:04.697 回答
1

在这种情况下使用 LDAP 条目等效于请求目录服务器使用应用程序提供的信息对连接进行身份验证。就 LDAP 而言,身份验证意味着现有的 LDAP会话(即与目录服务器的连接)已通过成功的 BIND 请求更改其身份验证状态。

Web 应用程序应向用户请求适当的信息以进行身份​​验证,并将此信息作为 BIND 请求提供给目录服务器。所需信息因 Web 应用程序(LDAP 客户端)使用的身份验证方法而异:

  • 一个简单的 BIND 请求需要一个专有名称和一个密码。此可分辨名称和密码应作为简单的 BIND 请求通过安全连接传输到目录服务器。
  • 使用预定义 SASL 机制的 SASL BIND 请求。机制因服务器而异,范围从 GSSAPI 到 PLAIN。

目录服务器收到 BIND 请求后,会立即将连接的身份验证状态更改为匿名并处理 BIND 请求。如果可以成功处理该请求,则目录服务器使用包含整数结果代码零 (0) 的 BIND 响应来响应 LDAP。这表明专有名称或用户名能够成功进行身份验证。

Web 应用程序应该使用某种机制来维护身份验证状态,并在身份验证状态更改时向目录服务器发出 BIND 请求。这可能是会话超时或其他一些机制。选择的方法不应由用户更改。

总之,使用目录服务器检查身份验证凭据并使用会话框架来管理身份验证状态。

编辑:

似乎这是一个有争议的答案。

  • 使用 cookie 不能处理浏览器禁用 cookie 的情况,并且在使用会话时,cookie 不是保持身份验证状态所必需的。
  • 会话不需要密码,也不应该在内存或会话中存储任何敏感信息,如密码。当身份验证状态过期(如果有)或会话过期(如果有)时,应用程序应该请求密码。
于 2012-08-12T15:59:23.067 回答