如何在使用WCF服务的WPF应用程序中集成LDAP

时间:2017-12-10 00:03:26

标签: c# wpf wcf authentication ldap

我将首先描述我的应用程序如何在没有LDAP的情况下工作。 我有使用WCF服务的WPF应用程序(身份验证 windows UserName 取决于用户选择)。该服务允许与数据库通信。

我向用户显示"登录屏幕"为了让他能够设置她的用户名"和#34;密码"然后应用程序连接到服务并使用检查UserName和Password是否存在于数据库中的函数。 (见下面的img) enter image description here

现在我还需要集成LDAP以根据现有系统验证用户帐户,而不必创建另一个登录帐户。

我对LDAP一无所知,对许多事情感到困惑。请原谅可能使用错误的术语。

我用谷歌搜索,但我仍然没有很多问题的答案。

1-我的数据库表中存在的用户与#34; User"之间的关系是什么?和我应该在LDAP中创建的配置文件?

2-我应该做些什么来允许用户从LDAP访问我的应用程序并使用我服务的所有功能?

3-我应该有服务类型" LDAP"就像我今天在我的应用程序中使用的其他身份验证类型(" Windows"和" UserName")?

4-如果我想更新上图所示的应用程序架构,我应该在哪里添加LDAP?

1 个答案:

答案 0 :(得分:4)

首先,我将逐一回答您的问题,

  1. LDAP上的用户在数据库中是相同的,您可以在用户表中保存LDAP的用户名及其域名, 但LDAP上的配置文件可能因配置文件表而异,但可以从LDAP地址获取。

  2. 通过LDAP检查用户名和密码就足够了,只需要在表中保存LDAP地址(例如ExternalPath)并在User和ExternalPath表之间建立关系。 LDAP地址包含一些规范。

  3. 是的,您必须有一个单独的机制来识别LDAP用户,我将进一步解释。

  4. 如果一切都是原子的并且设计得恰到好处,这并不难,在进一步的步骤中你可能会觉得它很容易。

  5. 让我讲述我在LDAP和身份验证用户LDAP和DB以及我们的架构方面的经验。

    我实现了一个名为Auth.svc的WCF服务,此服务包含一个名为AuthenticateAndAuthorizeUser的方法,这对于来自LDAP或任何地方的用户来说是透明的。

    我希望您通过以下步骤获得通过LDAP和DB对用户进行身份验证的线索和体系结构:

    1 - 首先我有一个名为Users的表,其中包含用户信息,还有一个名为ExternalPath的字段作为外键,如果为空则指定UserName在DB中知道它的密码,否则它来自UserDirectory

    2 - 在第二步中,您必须保留LDAP地址(在我的情况下,LDAP地址在ExternalPath表中),所有LDAP地址通常都在端口389上。

    3 - 实施身份验证用户,如果找不到(使用用户名和密码),请检查ExternalPath以验证LDAP地址。

    4 - 数据库架构应该类似于下面的屏幕截图。

    enter image description here

    如您所见,ExternalPath字段指定用户是否来自LDAP。

    5 - 在表示层我定义了LDAP服务器,如下面的截图

    enter image description here

    6 - 在另一方面,在系统中添加新用户时,您可以为我的用户定义LDAP我在添加用户表单时在DropDown中列出LDAP标题(如果管理员选择然后,LDAP地址不需要获取密码并将其保存在DB 中,因为我提到只需要保存LDAP用户名而不是密码。

    7 - 但最后一件事是在LDAP和DB上验证用户。

    因此,身份验证方法类似于:

    User userLogin = User.Login<User>(username, password, ConnectionString, LogFile);
    if (userLogin != null)
        return InitiateToken(userLogin, sourceApp, sourceAddress, userIpAddress);
    else//Check it's LDAP path
    {
        User user = new User(ConnectionString, LogFile).GetUser(username);
        if (user != null && user.ExternalPath != null)
        {
            LDAPSpecification spec = new LDAPSpecification
            {
                UserName = username,
                Password = password,
                Path = user.ExternalPath.Path,
                Domain = user.ExternalPath.Domain
            };
            bool isAthenticatedOnLDAP = LDAPAuthenticateUser(spec);
    
        }
    }
    

    如果输入的用户名和密码在DB中不存在userLogin,那么我们应该通过相关的LDAP地址对其进行身份验证。

    else阻止中找到User from Users表,如果此字段不为null,则获取ExternalPath表示用户在LDAP上。

    8 - LDAPAuthenticateUser方法是:

    public bool LDAPAuthenticateUser(LDAPSpecification spec)
    {
        string pathDomain = string.Format("LDAP://{0}", spec.Path);
        if (!string.IsNullOrEmpty(spec.Domain))
            pathDomain += string.Format("/{0}", spec.Domain);
        DirectoryEntry entry = new DirectoryEntry(pathDomain, spec.UserName, spec.Password, AuthenticationTypes.Secure);
        try
        {
            //Bind to the native AdsObject to force authentication.
            object obj = entry.NativeObject;
            DirectorySearcher search = new DirectorySearcher(entry);
    
            search.Filter = "(SAMAccountName=" + spec.UserName + ")";
            search.PropertiesToLoad.Add("cn");
            SearchResult result = search.FindOne();
            if (null == result)
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            Logging.Log(LoggingMode.Error, "Error authenticating user on LDAP , PATH:{0} , UserName:{1}, EXP:{2}", pathDomain, spec.UserName, ex.ToString());
            return false;
        }
        return true;
    }
    

    如果在LDAPAuthenticateUser中引发异常,则表示用户目录中不存在用户。

    身份验证代码接受域,用户名,密码以及Active Directory中树的路径。

    上面的代码使用LDAP目录提供程序验证方法调用LDAPAuthenticateUser并传入从用户收集的凭据。然后,使用目录树的路径,用户名和密码创建DirectoryEntry对象。 DirectoryEntry对象尝试通过获取AdsObject属性来强制NativeObject绑定。如果成功,则通过创建CN对象并过滤DirectorySearcher来获取用户的SAMAccountName属性。在用户进行身份验证并且异常未发生后,方法返回true表示用户在给定的LDAP地址上查找。

    要查看有关轻量级目录访问协议的更多信息并对其进行身份验证,THIS Link可以提供更多有关规范的信息。

    希望能帮助你。