从ASP.NET应用程序查询Active Directory对象属性将返回旧结果
Querying an Active Directory object property from ASP.NET application returns old results
几天来,我一直在尝试使用一些基于Active Directory的自定义身份验证。这一切都在理论上可行,但显然我的理论是错误的。登录到域的用户在登录到ASP.NET应用程序时,会在Active Directory中的自己的属性字段中写入字符串令牌(例如PIN码)(哪一个并不重要,但我使用了primaryInternalISDNNumber)。此PIN始终以编程方式生成和写入。
大致解释一下,web浏览器加载一个Java小程序,然后加载一个用C++编写的本地DLL,该DLL生成PIN并将其写入当前用户的Active Directory字段。然后,该DLL将生成的PIN返回给小程序,小程序将其传递给浏览器,浏览器使用返回的数据执行AJAX调用以启动身份验证。有权访问AD的应用程序读取连接用户对象的此字段值,并检查它是否与用户提供的匹配。如果PIN码匹配,则用户已成功通过身份验证。
这是ASP.NET应用程序用于读取AD:的示例代码
using (var de = new DirectoryEntry("LDAP://" + domainName))
{
using (var adSearch = new DirectorySearcher(de))
{
// Get user from active directory.
adSearch.Filter = "(sAMAccountName=" + userName.Trim().ToLower(CultureInfo.CurrentCulture) + ")";
var adSearchResult = adSearch.FindOne();
var entry = adSearchResult.GetDirectoryEntry();
var pinCodeProp = entry.Properties["primaryInternationISDNNumber"];
return pinCodeProp != null ? pinCodeProp.Value : string.Empty;
}
}
这通常效果很好。但是通常是不可接受的。它需要始终有效。
问题在于,ASP.NET应用程序有时会获取以前在该字段中的值,而不是实际值。好像有某种缓存。我尝试添加de.UsePropertyCache = false
,但结果相同。
出于测试目的,我创建了两个Win32控制台应用程序。一个写PIN码,另一个读PIN码。他们总是工作得很好!
我想,这一定是IIS应用程序池的问题。因此,我创建了一个本机DLL,它由ASP.NET应用程序使用平台调用加载。这个DLL创建一个新线程,调用CoInitialize并读取PIN码。这是代码:
pszFqdn = argv[1];
pszUserName = argv[2];
pszPassword = argv[3];
IADs *pObject = NULL;
HRESULT hr = S_OK;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = ADsOpenObject(pszFqdn, pszUserName, pszPassword, ADS_SECURE_AUTHENTICATION, IID_IADs, (LPVOID*)&pObject);
if (SUCCEEDED(hr) && pObject)
{
VARIANT var;
VariantInit(&var);
hr = pObject->Get(CComBSTR("primaryInternationalISDNNumber"), &var);
if ((SUCCEEDED(hr) && var.bstrVal) || hr == 0x8000500d)
{
if (hr != 0x8000500d)
{
// convert the BSTR received to TCHAR array
std::wstring wsValue(var.bstrVal, SysStringLen(var.bstrVal));
// copy the received value to somewhere
// ... not relevant
}
VariantClear(&var);
}
pObject->Release();
}
}
CoUninitialize();
令我惊讶的是,这段代码在正常工作了一天后,开始返回以前的值,就像以前的托管代码一样!
所以现在我想,好吧,我无法逃离IIS应用程序池,由于这一定是IIS应用程序库的问题,我将创建一个本机Windows应用程序,我将使用Process.Start方法执行该应用程序。我将通过进程退出代码返回我的PIN码(因为它无论如何都是整数)。该应用程序使用与上述DLL类似的C++代码。
所以我启动我的应用程序,等待它完成,读取退出代码。返回错误的值!
但是,好吧,我想说,这个过程是使用当前的用户凭据启动的,这也是IIS应用程序池。因此,我使用不同的凭据启动应用程序。你猜怎么着。。。。。它再次返回旧值(?!?!?)。
我还以为Java是地狱。。。有人知道这里可能发生了什么吗?
这确实是复制。由于我不想在读取字段之前强制复制(无论如何,这可能是一项耗时的操作),我想出了一个主意,从每个域控制器读取此字段,并检查其中是否有字段与提供的值匹配。
由于它可能会对某些人有所帮助,我使用以下代码做到了这一点。
var ctx = new DirectoryContext(
DirectoryContextType.DirectoryServer,
ipAddress,
userName, // in the form DOMAINUserName or else it would fail for a remote directory server
password);
var domain = Domain.GetDomain(ctx);
var values = new List<string>();
foreach (DomainController dc in domain.DomainControllers)
{
using (var entry =
new DirectoryEntry(
"LDAP://" + dc.IPAddress,
userName,
password))
{
using (var search = new DirectorySearcher(entry))
{
search.Filter = "(&(primaryInternationalISDNNumber=*)(sAMaccountName=" + userName + "))";
var result = search.FindOne();
var de = result.GetDirectoryEntry();
if (de.Properties["primaryInternationalISDNNumber"].Value != null)
{
values.Add(de.Properties["primaryInternationalISDNNumber"].Value.ToString());
}
}
}
}
- 从 lambda 返回的对象将丢失属性值
- 返回的指针属性中类实例上的矢量属性消失
- 如何通过对象的类属性删除对象,并返回其对象值?
- 类对象属性是否可以调用返回属性应具有的值的方法C++?
- 从基于属性的列表中返回随机对象
- 返回对象会丢失属性
- C++ 使用成员函数返回结构体指针属性的值
- 如何从类中返回自定义数组项目并操纵其属性?C
- 从const函数返回非const属性参考
- 用于指示返回值生存期的C++函数属性和参数相同
- 按属性搜索对象的向量并返回迭代器
- GCC 错误:如果已知函数正常返回,则函数可能是属性"pure"的候选者
- 从QT C 返回自定义对象,并在QML中打印属性
- GLSL属性位置返回-1
- BGL:邻接列表为描述符返回错误的边缘属性
- 为什么对象属性的值在 c++ 中将其指针添加到映射后返回零
- 返回泛型函数中对象的引用(具有指针或非指针属性)
- 从ASP.NET应用程序查询Active Directory对象属性将返回旧结果
- Stat() 函数返回值 -1,因此无法访问文件属性.我该如何纠正这一点
- 为什么glGetAttribLocation为两个不同的属性返回相同的值