我有一个JSF Web应用程序,它使用cookie进行自动身份验证,而无需提示输入用户名和密码。它使用带有用户名和随机 UUID 的 cookie,并使用WebFilter
进行重定向。
当客户端没有cookie时,身份验证通过HttpServletRequest #login(字符串用户名,字符串密码)完成。在后台,此方法使用 JAAS 认证,并在后台使用 LDAP
服务器。
当我的应用程序通过包含用户ID和UUID的cookie识别用户时,我的问题就来了。在这种情况下,
- 应用程序不知道密码,因此无法使用方法
HttpServletRequest #login(String username, String password)
。 - 我应该通过 JNDI 向 LDAP 服务器询问密码吗?乍一看这似乎是不可能的
- 或者,我可以将密码存储在我的数据库中。但这意味着信息的重复,我不喜欢它。
- 我见过周围的人简单地将属性"角色"设置为会话,但这似乎并不等同于 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
}
}
要以自定义方式进行实际的容器登录(在您的情况下,通过 cookie 和 UUID 而不是密码),您需要创建自己的登录模块。
Java EE中的专用API是JASPI/JASPIC(人们永远无法完全同意名称,从而使例如Google查询复杂化)。
登录模块处于完全控制状态,无需向 LDAP 服务器进行身份验证(如果您的应用程序可以在本地 100% 确定 cookie 是否有效)。您可能必须授权用户(向 ldap 服务器询问用户拥有的角色/组)。
作为JASPI/JASPIC的替代方案,您还可以查看服务器正在使用的专有登录模块机制。
在这种情况下,使用 LDAP 条目等效于请求目录服务器使用应用程序提供的信息对连接进行身份验证。就 LDAP 而言,身份验证意味着现有 LDAP 会话(即与目录服务器的连接)已通过成功的 BIND 请求更改了其身份验证状态。
Web 应用程序应从要进行身份验证的用户请求适当的信息,并将此信息作为 BIND 请求提供给目录服务器。所需信息因 Web 应用程序(LDAP 客户端)使用的身份验证方法而异:
- 简单的 BIND 请求需要可分辨名称和密码。此可分辨名称和密码应作为简单的 BIND 请求通过安全连接传输到目录服务器。
- 使用预定义的 SASL 机制的 SASL 绑定请求。机制因服务器而异,范围从 GSSAPI 到 PLAIN。
后,目录服务器会立即将连接的身份验证状态更改为匿名并处理 BIND 请求。如果可以成功处理请求,目录服务器将使用 BIND 响应来响应 LDAP,其中包括整数结果代码零 (0)。这表示可分辨名称或用户名能够成功进行身份验证。
Web 应用程序应使用某种机制来维护身份验证状态,并在身份验证状态更改时向目录服务器发出 BIND 请求。这可能是会话超时或其他机制。用户不应更改所选方法。
总之,使用目录服务器检查身份验证凭据,并使用会话框架管理身份验证状态。
编辑:
似乎这是一个有争议的答案。
- 使用 Cookie
- 不会处理浏览器禁用 Cookie 的情况,并且在使用会话时不需要 Cookie 来维护身份验证状态。 会话
- 不需要密码,也不应在内存或会话中存储任何敏感信息,如密码。应用程序应在身份验证状态过期(如果有)或会话过期(如果有)时请求密码。