2009-12-11 29 views
1

请帮忙!Login.aspx和捕获AD错误认证响应值

我是.NET web应用程序开发新手。我已经使用下面链接中的代码在Microsoft Live Single Sing On前面创建一个基本登录页面。

http://support.microsoft.com/default.aspx/kb/326340

我设法两个从SSO设置结合在一起(LiveSSO瓦特/表单验证)关断集成验证在IIS。如果用户使用AD成功进行身份验证,所有功能都可以正常工

我遇到的问题是,当用户无法验证它只会返回:“错误验证用户。登录失败:未知的用户名或密码错误“。当用户设置为在下次登录时更改密码时,此消息也会出现。我想要它做的是读取错误代码,确切地说为什么它失败,所以我可以设置重定向到密码重置页面(即如果错误是“用户标志设置为改变pswd”等等)

从上面链接的页面中,您可以看到LdapAuthentication.vb的VB代码,它可以验证帐户或在登录失败时返回错误消息。

返回错误验证用户的部分。登录失败:未知的用户名或密码错误”,是这个子程序处理:

  1. 抓住EX作为例外
  2. 抛出新的异常(‘错误认证用户’& ex.Message)
  3. 结束Try

这就是我一直在试图自定义以查看它如何根据用户帐户AD标志返回特定代码而不是通用消息。

有没有人有任何线索或想法我可以做到这一点?任何帮助将不胜感激。提前致谢!

回答

0

我敢肯定,您已经看到AD在给予所使用的技术时会抛出的最详细的错误。

当登录失败时,AD故意有点模糊,因为确切的原因。这可以防止黑客知道他们可能得到的是对或错的登录证书的哪一部分,从而拒绝他们根据从他们早期的失败中收集的信息来定制他们下一次尝试的能力。

要做你想做的事情,你将需要有不同的代码,使用应用程序的服务帐户设置连接到AD。然后,此代码需要获取用户提供的凭据,找到该用户的相关目录条目,然后阅读有关帐户重置标志等的信息。

一旦完成并且一切正常,您就会将控制权从实际的登录代码中移出,并尝试登录该用户。如果一切都不正常,您将重定向用户而不尝试使用他们自己的凭据登录。

[更新]

这里是如何“可能”去这样做这样的事情一个快速的代码示例:

Public Function DoesUserHaveToChangePassword(ByVal userName As String) As Boolean 

    Dim ctx As var = New PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain) 
    Dim up As var = UserPrincipal.FindByIdentity(ctx, userName) 
    Return (Not up.LastPasswordSet.HasValue AndAlso Not up.PasswordNeverExpires) 
    'returns true if last password set has no value and the password never expires option is not set. 

End Function 

VB是不是我的选择的母语,所以这是一个我在C#中嘲笑的快速示例的未经测试的转换。没有保证,这将完全按原样工作。

您需要导入System.DirectoryServices.AccountManagement命名空间才能使用它。

此示例中显示的PrincipalContext构造函数是非常基本的版本,并且仅在您的Web应用程序本身正在使用对您的活动目录具有必要访问权限的服务帐户进行读取时才有效。如果没有,请查看构造函数的重载,并使用允许您提供用于构建PrincipalContext的域用户和密码凭证的重载。

此处函数的主要观点是检查用户帐户即将尝试登录的LastPasswordSet值和AD的PasswordNeverExpires值。如果这两个都未设置,那么用户的帐户将要求他们在登录之前更改密码。

因此,您只需在尝试对用户进行身份验证之前调用此函数即可。如果函数返回true,那么用户无法登录,直到他们更改密码,并且应该将用户重定向到更改密码页面。

+0

嗨Stephen, 感谢您的回复。不幸的是,我没有这种经验来编写这样的代码。从逻辑上讲,它是有道理的,我明白你在说什么,但我会知道从哪里开始编码。我可以使用网络上的任何内容吗?或者也许添加到提供给上面链接的代码? – Vince 2009-12-14 19:34:04

+0

我做了一个函数的快速模拟,“应该”做一些你需要做的事情。我还没有测试过代码,所以没有承诺。 – 2009-12-14 22:55:04

+0

太棒了!谢谢Stephen。我将在VB.net中尝试它,并让你知道,但如果你有C#代码,我也希望看到这一点,因为我也有用C#编码的相同页面。 – Vince 2009-12-15 17:54:39

0

Stephen,

我终于把它工作了!谢谢!谢谢!

我不得不做出一些改变的VB代码如下所示:

Public Function DoesUserHaveToChangePassword(ByVal userName As String) As Boolean 

     Dim ctx As PrincipalContext = New PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain) 
     Dim up = UserPrincipal.FindByIdentity(ctx, userName) 
     Return (Not up.LastPasswordSet.HasValue) 
     'returns true if last password set has no value. 

    End Function 

随后的Login.aspx页面上我必须包括这样的:

sub Login_Click(sender as object,e as EventArgs) 
    Dim adPath As String = "LDAP://DC=xzone,DC=com" 'Path to your LDAP directory server 
    Dim adAuth As LdapAuthentication = New LdapAuthentication(adPath) 
    'Dim adUserPwd As DoesUserHaveToChangePassword = New DoesUserHaveToChangePassword(txtUsername.Text) 
    Try 
     If (True = adAuth.DoesUserHaveToChangePassword(txtUsername.Text)) Then 
      Response.Redirect("http://passwordresetpage") 

     ElseIf (True = adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) Then 
      Dim groups As String = adAuth.GetGroups() 

我因为我们的政策不允许普通用户使用“永不过期”,所以删除了密码到期检查。

IIS中的应用程序已启用匿名登录,但在AD帐户设置下运行。我将尝试使用通用帐户,因为在我的测试中,我使用了具有域管理员权限的帐户。安全团队将不会那样..

+0

非常好!如果你感到慷慨,你可以接受我的答案,所以我得到的声誉:) – 2009-12-28 13:14:37