2013-03-25 19 views
10

Tôi có dịch vụ WCF chứa phương thức Login xác nhận tên người dùng và mật khẩu đối với thông tin đăng nhập máy cục bộ và sau một khoảng thời gian dường như ngẫu nhiên, nó sẽ ngừng hoạt động đối với một số người dùng.Lỗi khi sử dụng PrincipalContext.ValidateCredentials để xác thực đối với Máy cục bộ?

Lệnh đăng nhập thực tế trông như thế này:

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; 
} 

Điều này dường như làm việc tốt cho một vài ngày, sau đó nó sẽ đột ngột ngưng hoạt động đối với một số người sử dụng và ném ngoại lệ này:

Nhiều kết nối tới máy chủ hoặc tài nguyên được chia sẻ bởi cùng một người dùng, sử dụng nhiều tên người dùng, không được phép. Ngắt kết nối tất cả các kết nối trước đó với máy chủ hoặc tài nguyên được chia sẻ và thử lại. (Ngoại lệ từ HRESULT: 0x800704C3)

tại System.DirectoryServices.AccountManagement.CredentialValidator.BindSam (String mục tiêu, String userName, String password)

tại System.DirectoryServices.AccountManagement.CredentialValidator.Validate (String userName, string password)

tại System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials (string userName, string password)

tại MyNamespace.LoginService.Login (string username, string password, string IPAddress) trong C: \ Users \ m e \ Desktop \ somefolder \ LoginService.svc.cs: dòng 67

Dòng 67 là: if (pContext.ValidateCredentials(username, password))

Tôi không chắc chắn nếu nó quan trọng hay không, nhưng dòng cuối cùng của thông báo lỗi là đường dẫn của giải pháp VS trên máy phát triển của tôi, không phải đường dẫn đến các tệp trên máy chủ sản xuất.

Khi không thành công, nó chỉ thất bại đối với một số người dùng, trong khi những người khác có thể tiếp tục đăng nhập tốt. Điều duy nhất tôi đã tìm thấy để tạm thời sửa lỗi là chạy iisreset. Dừng/khởi động trang web hoặc tái chế nhóm ứng dụng không hoạt động.

Tôi không thể tạo lại lỗi theo yêu cầu. Tôi đã thử đăng nhập với cùng một người dùng từ nhiều phiên và địa chỉ IP, đăng nhập với những người dùng khác nhau từ cùng một phiên trình duyệt cùng lúc, gửi spam nút Đăng nhập để thử và chạy nó nhiều lần, v.v. nhưng mọi thứ xuất hiện để làm việc tốt.

tôi có thể nhìn thấy từ khai thác gỗ của chúng tôi đã được người dùng đã thành công có thể đăng nhập trong quá khứ:

 
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 

Lý do chúng tôi xác thực đối với máy tính cục bộ là bởi vì người dùng có tài khoản được tạo tại địa phương để truy cập FTP, và chúng tôi không muốn xây dựng hệ thống đăng nhập tùy chỉnh của riêng mình hoặc làm cho người dùng của chúng tôi nhớ hai bộ thông tin đăng nhập.

Mã chỉ nên xác thực thông tin đăng nhập của người dùng và không làm bất kỳ điều gì khác với thông tin đăng nhập của người dùng. Không có mã nào khác sử dụng System.DirectoryServices, không có tệp IO xảy ra và không có quyền truy cập vào bất kỳ nội dung nào trên hệ thống tệp khác với các tệp cần thiết để chạy ứng dụng web.

Điều gì có thể khiến lỗi xuất hiện, dường như ngẫu nhiên sau một vài ngày? Và làm thế nào tôi có thể sửa nó?

Máy chủ là Windows Server 2003, chạy IIS 6.0, và nó được thiết lập để sử dụng .Net Framework 4.0

Trả lời

4

Gần nhất tôi có thể tìm thấy trực tuyến đối với việc giải thích vấn đề này là this forum post, nơi người dùng có trải qua những lỗi tương tự và được phát lại ghi rõ:

Nhà cung cấp WinNT không hoạt động tốt trong môi trường máy chủ. Tôi là thực sự ngạc nhiên khi bạn không thấy điều này với tải nhỏ hơn nhiều. Tôi có chỉ có thể nhận được điều này chỉ với 2 hoặc 3 người dùng.

this SO comment nêu

Cách NHẤT để xác thực một cách chính xác ai đó đang sử dụng LogonUserAPI như @stephbu viết. Tất cả các phương pháp khác được mô tả trong bài viết này sẽ không LÀM VIỆC 100%

nơi "tất cả các phương pháp khác" bao gồm đầu bình chọn câu trả lời của việc sử dụng PrincipalContext.ValidateCredentials

của nó nghe có vẻ như PrincipalContext.ValidateCredentials là không hoàn toàn 100% đáng tin cậy trên Windows Server 2003 và IIS6.0, vì vậy tôi viết lại mã xác thực của mình để sử dụng phương thức Win2I LogonUser thay thế.

[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)) 
{ 
    ... 
} 
+0

tôi đã lãng phí vài giờ, nhờ rachel, –

Các vấn đề liên quan