首先,我将描述我的应用程序在没有LDAP的情况下是如何工作的。我的WPF应用程序使用WCF服务(身份验证、窗口、或UserName取决于用户的选择)。此服务允许与数据库进行通信。
我向用户显示一个“登录屏幕”,以便让他设置她的“用户名”和“密码”,然后应用程序连接到服务,并使用检查数据库中是否存在UserName和密码的函数。(见下文img )
现在,我还需要集成LDAP,以便根据现有系统对用户帐户进行身份验证,而不必创建另一个登录帐户。
我对LDAP有点无知,对许多事情感到困惑。请原谅可能使用了错误的术语。
我在谷歌上搜索过,但我仍然没有很多问题的答案。
1-存在于我的数据库表"User“中的用户和我应该在LDAP中创建的配置文件之间的关系是什么?
2-我应该做什么检查才能允许来自LDAP的用户访问我的应用程序并使用我的服务的所有功能?
3-我是否应该像我的应用程序(“UserName”和"UserName")中的其他身份验证类型一样,使用"LDAP“服务类型?
4-如果我想更新上面图片中描述的应用程序体系结构,我应该在哪里添加LDAP?
发布于 2018-01-07 01:20:57
首先我要逐一回答你的问题,
因此,让我讲述我在LDAP方面的经验,并在LDAP和DB以及我们的架构上对用户进行身份验证。
我实现了一个名为Auth.svc
的WCF服务,该服务包含一个名为AuthenticateAndAuthorizeUser
的方法--这对于来自LDAP或任何地方的用户来说都是透明的。
我希望通过以下步骤获得通过LDAP和DB对用户进行身份验证的线索和体系结构:
1-首先,我有一个名为Users
的表,它保存用户信息,还有一个名为ExternalPath
作为外键的字段,如果为null,则在DB中指定UserName,否则它来自UserDirectory
。
2-在第二步中,您必须保存LDAP地址(在我的例子中,LDAP地址在ExternalPath
表中),所有LDAP地址通常都在端口389
上。
3-实现对用户身份验证的,如果找不到(带有用户名和密码),那么检查它的ExternalPath
来验证LDAP地址。
4-数据库模式应该类似于下面的屏幕截图。
如您所见,ExternalPath
字段指定用户是否来自LDAP。
5-在表示层中定义LDAP服务器,如下面的屏幕截图所示
6-在系统中添加新用户时,您可以为用户定义LDAP --在我的示例中,我在添加用户表单中列出了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);
}
}
如果通过输入userLogin
和密码在DB中不存在UserName,那么我们应该通过相关的LDAP地址对其进行身份验证。
在else
块中,从User表中查找User并获得它的ExternalPath
,如果这个字段不是null,就意味着用户在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中的域、用户名、密码和树的路径。
上面的代码使用LDAP目录提供程序,身份验证方法调用LDAPAuthenticateUser
并传入从用户收集的凭据。然后,使用目录树的路径、用户名和密码创建一个DirectoryEntry对象。DirectoryEntry
对象试图通过获取AdsObject
属性强制NativeObject
绑定。如果成功,用户的CN
属性是通过创建DirectorySearcher
对象和过滤SAMAccountName
获得的。在对用户进行身份验证和异常未发生之后,方法返回true意味着用户在给定LDAP地址上查找。
要查看有关轻量级目录访问协议的更多信息并对其进行身份验证,这个链接可能是有用的,它可以提供更多关于规范的信息。
希望会帮助你。
https://stackoverflow.com/questions/47734516
复制