Jsf 使用HttpServletRequest和LDAP自动登录

Jsf 使用HttpServletRequest和LDAP自动登录,jsf,jakarta-ee,authentication,jaas,jaspic,Jsf,Jakarta Ee,Authentication,Jaas,Jaspic,我有一个JSFWeb应用程序,它使用cookies进行自动身份验证,而不提示输入用户名和密码。它使用带有用户名和随机UUID的cookie,并使用WebFilter进行重定向 当客户端没有cookie时,身份验证通过。在幕后,这种方法使用JAAS身份验证,并在背后使用LDAP服务器 当我的应用程序通过保存userid和UUID的cookies识别用户时,我的问题就来了。在这种情况下, 应用程序不知道密码,因此无法使用方法HttpServletRequest#login(字符串用户名、字符串密码)

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

当客户端没有cookie时,身份验证通过。在幕后,这种方法使用JAAS身份验证,并在背后使用
LDAP
服务器

当我的应用程序通过保存userid和UUID的cookies识别用户时,我的问题就来了。在这种情况下,

  • 应用程序不知道密码,因此无法使用方法
    HttpServletRequest#login(字符串用户名、字符串密码)
  • 我应该通过JNDI询问LDAP服务器的密码吗?乍一看,这似乎是不可能的
  • 或者,我可以将密码存储在数据库中。但这意味着信息的重复,我不喜欢这样
  • 我见过人们简单地将属性“role”设置为会话,但这似乎并不等同于JAAS登录。“等效”是指能够使用
    isUserInRole()
    getUserPrincipal()
    方法
  • 所以,问题是:在这种情况下,我应该如何登录用户?我希望问题现在更清楚了

    编辑

    为了让代码说话,我添加了托管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
            }
        }
    

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

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

    • 简单绑定请求需要可分辨名称和密码。此可分辨名称和密码应通过安全连接作为简单绑定请求传输到目录服务器
    • 使用预定义SASL机制的SASL绑定请求。每台服务器的机制各不相同,范围从GSSAPI到普通
    收到绑定请求后,目录服务器将立即将连接的身份验证状态更改为匿名,并处理绑定请求。如果请求可以成功处理,目录服务器将使用绑定响应响应LDAP,其中包含一个整数结果代码零(0)。这表示可分辨名称或用户名能够成功进行身份验证

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

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

    编辑:

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

    • 使用Cookie不会处理浏览器禁用Cookie的情况,并且在使用会话时不需要Cookie来维护身份验证状态
    • 会话不需要密码,也不应该在内存或会话中存储任何敏感信息,如密码。当身份验证状态过期(如果有)或会话过期(如果有)时,应用程序应请求密码
    要以自定义方式(在您的情况下,通过cookie和UUID而不是密码)进行实际的容器登录,您需要创建自己的登录模块

    javaee中用于此目的的专用API是JASPI/JASPIC(人们永远不会完全同意这个名称,这使例如google查询变得复杂)

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


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

    如果LDAP设置正确,则无法从LDAP获取密码。你为什么认为你需要它?你没有,哇!事实上,我还没能得到密码。我认为这是一个许可问题。为什么我不需要密码?密码是用于身份验证的。LDAP已经完成了身份验证。你不需要它。您认为为什么要这样做?在此会话中,用户尚未进行身份验证。他在上一次会话中这样做了,当时应用程序创建了cookies并将它们的值保存在数据库中。在此会话中,应用程序读取Cookie,将值与保存在db中的值进行比较,并决定应自动对用户进行身份验证。因此,您不需要密码,因为他必须已在上一会话中提供了密码。您根本不需要返回LDAP。你需要的一切都应该在旧的会话中出现。听起来你在告诉询问者去做一些他或她要求如何做的事情。引导他们绕圈-1如果你问我的话。@BillR这里不太清楚用户到底在问什么,你可以给出一个正确完整的答案。谢谢你的回答。我知道我需要通过在应用程序的数据库中保存密码或创建自定义SAM模块来处理此逻辑。