5

一段时间以来,我一直在寻找解决方案,但不幸的是,每个线程都是死胡同。

我正在开发一个仅由我们公司内部使用的 C#/ASP.net Web 应用程序。在 IIS 和我的 web.config 文件中,匿名访问已被关闭,强制 IIS 使用 Windows 身份验证用户(Active Dir 用户)。

我的问题是以下代码可以完美地获得所需的(或任何)AD 用户:

using System.DirectoryServices.AccountManagement;

... other code ...

PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "mydomain", "someADuser", "someADuserpassword");
UserPrincipal winuser = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "samaccountname");

上面 PrincipalContext 中使用的“someADuser”是当前通过 windows 登录的用户,因此经过身份验证,是一个有效的 AD 用户。使用以下代码(完全相同的用户仍然登录)给我一个“登录失败:未知用户名或密码错误”错误:

PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "mydomain");
UserPrincipal winuser = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "samaccountname");

如果未在 PrincipalContext 对象中指定,则 UserPrincipal.FindByIdentity 似乎出于某种原因不使用已登录用户的验证凭据 - 这是我不想做的事情。

即使必要的设置(我希望)添加到 web.config 中,ctx 是否有可能由于某种原因没有获取登录的 Windows 用户:

<authentication mode="Windows"/>
<authorization>
  <deny users="?"/>
</authorization>

并且在 IIS 中完全禁用了匿名访问?

4

4 回答 4

11

如果未在 PrincipalContext 对象中指定,则 UserPrincipal.FindByIdentity 似乎出于某种原因不使用已登录用户的验证凭据 - 这是我不想做的事情。

UserPrincipal.FindByIdentity 根本不关心用户的凭据。您只是在执行查找以查看该帐户是否存在。您收到错误的原因是因为默认用户凭据(即您的 Web 应用程序运行的身份)无权访问该目录,因此它无法执行查找。当您将客户端的凭据传递给 PrincipalContext 时,问题就消失了,因为您的客户端具有可以访问该目录的有效 AD 帐户。

您应该调查正在使用哪个身份来运行应用程序池,并确保它可以访问该目录。

于 2013-04-09T14:04:57.950 回答
2

很烦人,尽管如果关闭匿名访问,当前主体将默认为登录到 Windows 的用户。事实证明它不像@RogerN 所指出的那样。

使用@TheKingDave 提到的以下语句,它基本上模拟了登录到 Windows 的用户并使当前线程在其主体而不是“ASP”(在我的情况下)帐户上运行。

因为我们域中的所有用户都具有对 Active Directory 的查询/读取访问权限,所以获得更多关于他们的详细信息应该不是问题,这正是我首先想要的。

结束代码(正在测试):

System.Web.HttpContext.Current.Request.LogonUserIdentity.Impersonate();
ctx = new PrincipalContext(ContextType.Domain, System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName);
UserPrincipal winuser = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "whicheveraccount");

希望它对将来有所帮助!谢谢!;-)

于 2013-04-09T15:21:38.060 回答
1

我做了很多搜索/研究来解决这个问题,但没有任何效果,最后,我所做的只是添加@到服务器名称、容器、用户名和密码,如下所示:

app.CreatePerOwinContext(() => new PrincipalContext(ContextType.Domain, @"abc.net", @"OU=Customers,DC=abc,DC=net", ContextOptions.SimpleBind, @"abcnet\authuser", @"!$%MyPassword"));

它奏效了。哦!

于 2015-05-19T06:53:34.263 回答
0

所以我发现了如何传递假冒身份。我有一种情况,作为管理员,我想自动解锁用户帐户。我必须将用户名放入变量并将它们传递给函数,如下所示:

string accountname = @"domain\username";
string admin = "adminusername";
string domain = Environment.UserDomainName;
string password = "password";
string dc = "WIN2K8DC1";  // example host name of domain controller, could use IP

// This determines the domain automatically, no need to specify
// Use the constructor that takes the domain controller name or IP, 
// admin user name, and password
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, dc, admin, password); 

UserPrincipal winuser = UserPrincipal.FindByIdentity(ctx, accountname)

if (winuser != null)
{
    WindowsImpersonationContext wic = Impersonation.doImpersonation(admin, domain, password); //class/function that does the logon of the user and returns the WIC
    if (wic != null)
    {
        winuser.UnlockAccount();
    }
} 

可用于返回 WIC 的模拟类功能可在 MSDN 上找到: https ://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx

于 2017-06-09T15:09:38.153 回答