2013-04-09 317 views
3

我一直在寻找这方面的解决方案一段时间,但每个线程不幸的是死路一条。尝试UserPrincipal.FindByIdentity时登录失败错误

我正在研究一个C#/ ASP.net web应用程序,它只能在我们公司内部使用。匿名访问已在IIS和我的web.config文件中关闭,迫使IIS使用Windows身份验证用户(Active Dir用户)。

我的问题是下面的代码完美地工作,以获得所需的(或任何)AD用户:在PrincipalContext使用

using System.DirectoryServices.AccountManagement; 

... other code ... 

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

“someADuser”以上是通过窗户登录的用户的电流,从而经过身份验证和有效的AD用户。使用下面的代码(使用完全相同的用户仍然登录)给了我一个“登录失败:未知的用户名或密码错误”的错误:

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

看来UserPrincipal.FindByIdentity不使用登录用户的如果未在PrincipalContext对象中指定,则由于某种原因验证凭证 - 我不想这样做。

是否有可能将CTX不拾取在Windows用户登录由于某种原因,即使进行必要的设置(我希望)被添加到web.config中:

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

和匿名访问在IIS中完全禁用?

+1

我米不知道为什么你试图以编程方式做到这一点为什么不使用模拟?那么您可以设置为特定的AD用户?那是你正在尝试做什么? – TheKingDave 2013-04-09 13:34:44

+0

@TheKingDave,我需要从AD获得更多的信息登录用户(帐户锁定/启用,GUID等),因为这个应用程序将托管在服务器上,被许多域访问。希望我明白你的问题并清楚回答? Thx为响应... – KDT 2013-04-09 13:42:54

+0

创建PrincipalContext对象后,“ctx.UserName”是什么? – jadarnel27 2013-04-09 14:02:21

回答

9

It seems UserPrincipal.FindByIdentity doesn't use the logged in user's validated credentials for some reason if it's not specified in the PrincipalContext object - something I don't want to do.

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

您应该调查使用哪个身份来运行应用程序池并确保它有权访问该目录。

+0

我听到你在说@RogerN,也许我完全失去了IIS的工作原理(在我的防守中,第一次我必须处理AD和这样的问题),但我的意见关闭IIS中的匿名访问并配置web-app的web.config文件以拒绝匿名访问会自动落在从aspx页面启动“线程”调用的用户身份上? – KDT 2013-04-09 14:19:02

+0

哦,并在IIS中打开“集成Windows身份验证” – KDT 2013-04-09 14:20:35

+0

从MS站点(http://msdn.microsoft.com/zh-cn/library/bb345952.aspx):“如果用户名和密码参数是都使用null,使用当前主体的默认凭据“。所以理论上我的代码应该可以工作,但事实并非如此。 – KDT 2013-04-09 14:38:14

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"); 

希望它可以帮助some1在未来!谢谢!;-)

+0

它没有为我工作,你想分享更多的细节,如应用程序池如何设置? – codebased 2014-07-15 06:17:30

+0

不知道你是否正确@codebased,但我的应用程序池是asp.net 4与经典的托管管道在网络服务标识下运行。在我的情况下,只有在默认网站下运行的应用程序启用了Windows身份验证作为应用程序。希望能帮助到你? – KDT 2014-11-14 09:44:40

0

我做了很多搜索/研究解决这个问题,但是毫无效果,最后,所有我所做的就是添加@为servername,容器,用户名密码&象下面这样:

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

它工作。卫生署!

+0

'app'是什么类型的变量? – vapcguy 2017-06-08 15:44:17

+0

其在MVC'Startup'配置类中的'public void ConfigureAuth(IAppBuilder app)' – 2017-06-09 06:37:09

+0

另外来自'Properties.Settings.Default.DomainName'的值也不用'@' – 2017-06-09 06:40:15

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