使用PrincipalContext.ValidateCredentials时,对本地机器验证错误?

2019-08-18 00:02发布

我有一个包含一个WCF服务Login该验证针对本地计算机凭证的用户名和密码,时间似乎是随机时间后,将停止对一些用户的工作方法。

实际的登录命令如下:

public UserModel Login(string username, string password, string ipAddress)
{
    // Verify valid parameters
    if (username == null || password == null)
        return null;

    try
    {
        using (var pContext = new PrincipalContext(ContextType.Machine))
        {
            // Authenticate against local machine
            if (pContext.ValidateCredentials(username, password))
            {
                // Authenticate user against database
                using (var context = new MyEntities(Connections.GetConnectionString()))
                {
                    var user = (from u in context.Users
                                where u.LoginName.ToUpper() == username.ToUpper()
                                      && u.IsActive == true
                                      && (string.IsNullOrEmpty(u.AllowedIpAddresses)
                                        || u.AllowedIpAddresses.Contains(ipAddress))
                                select u).FirstOrDefault();

                    // If user failed to authenticate against database
                    if (user == null)
                        return null;

                    // Map entity object to return object and assign session token
                    var userModel = Mapper.Map<User, UserModel>(user);
                    userModel.Token = Guid.NewGuid();
                    userModel.LastActivity = DateTime.Now;

                    // Authenticated users are added to a list on the server
                    // and their login expires after 20 minutes of inactivity
                    authenticatedUsers.Add(userModel);
                    sessionTimer.Start();

                    // User successfully authenticated, so return UserModel to client
                    return userModel;
                }
            }
        }
    }
    catch(Exception ex)
    {
        // This is getting hit
        MessageLog.WriteMessage(string.Format("Exception occurred while validating user: {0}\n{1}", ex.Message, ex.StackTrace));
        return null;
    }

    // If authentication against local machine failed, return null
    return null;
}

这似乎很好地工作了几天,然后它会突然停止对一些用户的工作,并抛出这个异常:

由同一个用户使用一个以上用户名与服务器或者共享资源有多个连接,是不允许的。 断开与服务器或共享资源的所有连接,然后再试一次。 (从HRESULT异常:0x800704C3)

在System.DirectoryServices.AccountManagement.CredentialValidator.BindSam(字符串对象,用户名字符串,字符串密码)

在System.DirectoryServices.AccountManagement.CredentialValidator.Validate(用户名字符串,字符串密码)

在System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials(用户名字符串,字符串密码)

在MyNamespace.LoginService.Login(字符串的用户名,密码字符串,字符串ip地址)在C:\用户\我\桌面\ somefolder \ LoginService.svc.cs:67行

第67行是: if (pContext.ValidateCredentials(username, password))

我不知道,如果它的事项或没有,但错误信息的最后一行是我的开发机器上的VS解决方案的路径,而不是路径到生产服务器上的文件。

当它失败时,它不仅不能为某些用户,而其他人可以继续登录就好了。 我已经找到了临时修复错误的唯一的事情是运行iisreset 。 停止/启动网站或回收应用程序池不起作用。

我无法重现上需求的错误。 我试着登录与多个会话和IP地址相同的用户,与在同一时间同一浏览器会话不同的用户登录,垃圾邮件的登录按钮尝试,并得到它多次运行等,但似乎一切做工精细。

我可以从我们的记录用户已经能够成功在过去的登录,请参阅:

3/21/2013
o   9:03a   I logged in
o   1:54p   UserB logged in
o   1:55p   UserA logged in
o   2:38p   UserB logged in
o   3:48p   UserB logged in
o   5:18p   UserA logged in
o   6:11p   UserB logged in

3/22/2013
o   12:42p  UserA logged in
o   5:22p   UserB logged in
o   8:04p   UserB logged in

3/25/2013 (today)
o   8:47a   I logged in
o   12:38p  UserB tries logging in and fails. Repeated ~15 times over next 45 min
o   1:58p   I login successfully
o   2:08p   I try to login with UserB's login info and fail with the same error

我们针对本地计算机进行身份验证的原因是因为用户在本地FTP访问创建一个帐户,我们不想建立自己的自定义登录系统或使我们的用户记住两组凭证。

该代码应该只验证用户的凭据,并没有做任何其他与用户的凭据。 还有的是,不使用其他代码System.DirectoryServices ,没有文件IO事情,并没有什么本地的访问比运行Web应用程序所要求的其他文件在文件系统上。

什么会导致出现该错误,看似随意,几天后? 我该如何解决?

该服务器是Windows Server 2003中,它运行IIS 6.0,它是设置为使用.Net框架4.0

Answer 1:

我可以在网上找到地解释了这个问题最接近的是这个论坛的帖子 ,当用户遇到同样的错误,并得到了重播,指出:

WinNT提供未在服务器环境中做的很好。 其实我惊讶,你没有看到这一个小得多的负荷。 我已经能够只用2个或3个用户拿到这个。

而这SO评论指出

要正确验证某人的最好办法是使用LogonUserAPI作为@stephbu写。 在这篇文章中描述的所有其他方法将无法正常工作100%

其中,“其他所有方法”包括使用顶部投答案PrincipalContext.ValidateCredentials

它听起来像PrincipalContext.ValidateCredentials是Windows Server 2003和IIS6.0在不能完全100%可靠的,所以我改写了我的验证码使用的LogonUser WinAPI的方法来代替。

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
    string lpszUsername,
    string lpszDomain,
    string lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    out IntPtr phToken
    );

IntPtr hToken;
if (LogonUser(username, "", password, 
    LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, out hToken))
{
    ...
}


文章来源: Error when using PrincipalContext.ValidateCredentials to authenticate against a Local Machine?