我正在使用Web Services
来针对Active Directory
对用户进行身份验证。我目前的解决方案是有效的,但是,我正在尝试采用不同的方法。
我有一个Active Directory
(生产),它位于防火墙后面。我还在Active Directory
中安装了DMZ
。他们之间有单向关系。 DMZ信任生产和生产并不关心DMZ
。
我想要完成的是通过DMZ Active Directory
对每个人进行身份验证。目前,根据用户名,我知道要对哪个AD
服务器进行身份验证。
例如,我的生产Active Directory(假设域 domain.local )和我的DMZ Active目录(假设域 domain.public )。在对任何AD服务器进行身份验证之前,我会检查其中一个服务器中是否存在提供的用户名。然后,我检查用户是否处于活动状态,然后才进行身份验证。 (我在第一个函数中遇到问题。它永远不会达到第二个或第三个函数。)
更新:添加所有内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using System.DirectoryServices.AccountManagement;
namespace ActiveDirectory
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Service1 : IService1
{
#region Does User Exist in AD
public string local = string.Empty;
public string ldappath = string.Empty;
public string userNameToUse = string.Empty;
public string domain = string.Empty;
public bool DoesUserExist(string userName)
{
string _userName = userName;
bool exist = true;
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
{
if (foundUser == null)
{
exist = false;
}
else
{
return exist;
}
}
}
return exist;
}
#endregion
#region Check if User Active
public bool isActive (string userName)
{
string _userNameToBeSearched = userNameToUse;
string _username = string.Empty;
string _pwd = string.Empty;
if (local == "YES")
{
_username = "xx";
_pwd = "xx";
ldappath = "LDAP://xxx/DC=xx, DC=local";
}
else
{
_username = "xx";
_pwd = "xx";
ldappath = "LDAP://xxx/DC=xx, DC=public";
}
bool isActive = true;
try
{
DirectoryEntry entry = new DirectoryEntry(ldappath, _username, _pwd);
DirectorySearcher search = new DirectorySearcher(entry);
entry.AuthenticationType = AuthenticationTypes.Secure;
search.SearchRoot = entry;
search.Filter = "(SAMAccountName=" + _userNameToBeSearched + ")";
SearchResult results = search.FindOne();
if (results.ToString() != "")
{
int flags = Convert.ToInt32(results.Properties["userAccountControl"][0].ToString());
//CHECK IF THE ACCOUNT IS DISABLED
if (flags == 66050)
{
isActive = false;
}
}
}
catch (DirectoryServicesCOMException ex)
{
ex.ToString();
}
return isActive;
}
#endregion
#region Is user authenticated
public string isAuthenticated (string userName, string pwd)
{
string _userName, _pwd, message;
_userName = userName;
_pwd = pwd;
char[] splitchar = { '@' };
string[] strSplit = _userName.Split(splitchar);
string z = strSplit[0];
if (strSplit.Length == 2)
{
domain = "x.public";
userNameToUse = z.ToString();
local = "NO";
}
else
{
domain = "x.local";
userNameToUse = z.ToString();
local = "YES";
}
if (DoesUserExist (userNameToUse) == true)
{
if (isActive(userNameToUse) == true)
{
try
{
DirectoryEntry entry = new DirectoryEntry(ldappath, userNameToUse, _pwd);
object nativeObject = entry.NativeObject;
var GUIDID = "";
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var user = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
{
if (user != null)
{
GUIDID = user.Guid.ToString();
}
}
message = "Successfully authenticated:" + GUIDID;
}
}
catch (DirectoryServicesCOMException)
{
message = "Invalid password.";
}
}
else
{
message = "Account is disabled";
}
}
else
{
message = "There's an issue with your account.";
}
return message;
}
#endregion
}
}
如果DMZ
AD中存在用户名,则返回true,否则返回false。但是,将会有用户只存在于生产AD中,但在DMZ中不会有任何条目。从那以后,我建立了一种信任,我应该能够做到这一点:
username@domain.local
用于生产和username@domain.public
但是,即使我指定完全用户名,如果DMZ AD中不存在条目,它将返回null,尽管它存在于生产AD中。
有关如何使用具有生产AD完全权限的webservices帐户DMZ AD
通过{{1}}验证所有人的任何建议吗?
注意如果需要我可以提供剩下的代码...... *
由于
答案 0 :(得分:0)
PrincipalContext中域的价值是多少?如果您还没有,那么您需要为正在查找用户当前代码的用户使用正确的域名。 PrincipalContext不支持在林中的域之间进行搜索。
以下是使用DirectorySearcher执行此操作的example。
答案 1 :(得分:0)
代码有几个问题,我只讨论主要问题。
在方法DoesUserExist
中,您使用服务帐户(没有凭据传递给PrincipalContext
)来查询这两个域。但是在方法isActive
中,您拥有不同域的不同凭据。所以我们有2个域的3个凭证......
至少对两种方法使用一致的方法。
对于单向信任(例如A信托B),B中的帐户应该能够访问域A和B.
可能您只需将受信任域中的帐户用作服务帐户即可。然后使用服务帐户(null到用户名和密码)来执行所有AD访问。因此,您甚至不需要在代码中输入密码。
在isActive
中," 66050"来自?
66060是10202十六进制,表示(1)用户,(2)禁用,(3)不会过期密码。
要检查帐户是否已启用,请仅检查ACCOUNTDISABLE位(0x0002)。启用时应为0。
您已在DoesUserExist
中获得UserPrincipal。只需查看UserPrincipal.Enabled
。
我需要在日常工作中进行代码审查。现在我也在Stack Overflow上做了... :))