使用PrincipalContext.ValidateCredentials对本地计算机进行身份validation时出错?
我有一个WCF服务,其中包含一个Login
方法,该方法根据本地计算机凭据validation用户名和密码,并且在看似随机的一段时间后,它将停止为某些用户工作。
实际的登录命令如下所示:
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.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; }
这似乎可以正常工作几天,然后它会突然停止为某些用户工作并抛出此exception:
不允许同一用户使用多个用户名与服务器或共享资源建立多个连接。 断开与服务器或共享资源的所有先前连接,然后重试。 (HRESULTexception:0x800704C3)
at System.DirectoryServices.AccountManagement.CredentialValidator.BindSam(String target,String userName,String password)
at System.DirectoryServices.AccountManagement.CredentialValidator.Validate(String userName,String password)
at System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials(String userName,String password)
at MyNamespace.LoginService.Login(String username,String password,String ipAddress)在C:\ Users \ me \ Desktop \ somefolder \ LoginService.svc.cs:第67行
第67行是: if (pContext.ValidateCredentials(username, password))
我不确定它是否重要,但错误消息的最后一行是我的开发机器上VS解决方案的路径,而不是生产服务器上文件的路径。
当它失败时,它只对某些用户失败,而其他用户可以继续正常登录。 我发现暂时修复错误的唯一办法是运行iisreset
。 停止/启动网站或回收应用程序池不起作用。
我无法按需重现错误。 我尝试使用来自多个会话和IP地址的同一用户登录,同时使用同一浏览器会话中的不同用户登录,向“登录”按钮发送垃圾邮件以尝试让其多次运行等,但所有内容都会显示工作正常。
我可以从我们的日志记录中看到用户已成功登录过去:
2013年3月21日 o 9:03a我登录了 o 1:54p UserB已登录 o 1:55p UserA已登录 o 2:38p UserB已登录 o 3:48p UserB已登录 o 5:18p UserA已登录 o 6:11p UserB已登录 2013年3月22日 o 12:42p UserA已登录 o 5:22p UserB已登录 o 8:04p UserB已登录 2013年3月25日(今天) 哦8:47a我登录了 o 12:38p UserB尝试登录并失败。 在接下来的45分钟内重复约15次 o 1:58p我成功登录 o 2:08p我尝试使用UserB的登录信息登录,但失败并出现同样的错误
我们对本地计算机进行身份validation的原因是因为用户在本地创建了一个用于FTP访问的帐户,我们不想构建自己的自定义登录系统或让我们的用户记住两组凭据。
代码应仅validation用户的凭据,并且不会对用户的凭据执行任何其他操作。 没有其他代码使用System.DirectoryServices
,没有文件IO正在进行,并且除了运行Web应用程序所需的文件之外,无法访问文件系统上的任何本地内容。
几天之后,看似随意出现的错误会导致什么? 我该如何解决?
服务器是运行IIS 6.0的Windows Server 2003,并且设置为使用.Net Framework 4.0
我能在网上找到最接近解释这个问题的是这个论坛post ,用户遇到相同的错误并得到重播说明:
WinNT提供程序在服务器环境中表现不佳。 我真的很惊讶你没有看到这个负载小得多。 我只能用2或3个用户获得此function。
这个SO评论说
正确validation某人的最佳方法是使用LogonUserAPI作为@stephbu写入。 本文中描述的所有其他方法都不会100%工作
其中“所有其他方法”包括使用PrincipalContext.ValidateCredentials
的最高投票答案
听起来像PrincipalContext.ValidateCredentials
在Windows Server 2003和IIS6.0上并不是完全可靠的,所以我重写了我的身份validation代码以使用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)) { ... }