2016-02-17 17 views
5

Tôi đang sử dụng ASP.Net Web API 2/.Net 4.5.2.Giữ lại chính bên trong mục công việc nền xếp hàng đợi

Tôi đang cố giữ lại tên gọi chính khi xếp hàng một mục công việc nền. Cuối cùng, tôi đang cố gắng để:

Thread.CurrentPrincipal = callingPrincipal; 

Nhưng khi tôi làm như vậy, tôi nhận được một ObjectDisposedException:

System.ObjectDisposedException: xử lý an toàn đã bị đóng cửa

thế nào thế nào để giữ nguyên hiệu trưởng hiện tại bên trong mục công việc nền?
Tôi có thể tạo bản sao của hiệu trưởng bằng cách nào đó không?

public void Run<T>(Action<T> action) 
{ 
    _logger.Debug("Queueing background work item"); 
    var callingPrincipal = Thread.CurrentPrincipal; 
    HostingEnvironment.QueueBackgroundWorkItem(token => 
    { 
     try 
     { 
      // UNCOMMENT - THROWS EXCEPTION 
      // Thread.CurrentPrincipal = callingPrincipal; 
      _logger.Debug("Executing queued background work item"); 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Fatal(ex); 
     } 
     finally 
     { 
      _logger.Debug("Completed queued background work item"); 
     } 
    }); 
} 
+0

Bạn có thực sự cần 'Thread.CurrentPrincipal' hoặc bạn thực sự cần' HttpContext.User'? Có lẽ giải thích lý do tại sao bạn cần phải truyền dòng hiệu trưởng như thế. –

+0

Lý do đằng sau việc giữ Nguyên tắc hiện tại trong Chủ đề nền là gì? – Win

+0

Ví dụ: để lấy một số dữ liệu cá nhân tốn rất nhiều thời gian. – VMAtm

Trả lời

5

Hóa ra ClaimsPrincipal bây giờ có một constructor sao chép.

var principal = new ClaimsPrincipal(Thread.CurrentPrincipal); 

Điều này dường như giải quyết được vấn đề trong khi giữ lại tất cả thông tin nhận dạng và xác nhận quyền sở hữu. Chức năng đầy đủ sau:

public void Run<T>(Action<T> action) 
{ 
    _logger.Debug("Queueing background work item"); 
    var principal = new ClaimsPrincipal(Thread.CurrentPrincipal); 

    HostingEnvironment.QueueBackgroundWorkItem(token => 
    { 
     try 
     { 
      Thread.CurrentPrincipal = principal; 
      _logger.Debug("Executing queued background work item"); 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Fatal(ex); 
     } 
     finally 
     { 
      _logger.Debug("Completed queued background work item"); 
     } 
    }); 
} 
0

Vấn đề trong trường hợp của bạn là nhiệm vụ nền được thực thi sau khi Thread.CurrentPrincipal được xử lý. Điều này xảy ra vì mô hình ASP.NET - yêu cầu đang được xử lý trong ngữ cảnh người dùng và sau đó tất cả các giá trị tương ứng với người dùng được giải phóng. Vì vậy, điều này là chính xác xảy ra với danh tính của bạn. Cố gắng lưu thông tin về người dùng và danh tính của người đó để mạo danh sau này.

Bạn có thể xem một support article from Microsoft mạo danh các hoạt động trong các trang web ASP.NET, nhưng tôi không nghĩ rằng điều này sẽ rất hữu ích cho bạn:

System.Security.Principal.WindowsImpersonationContext impersonationContext; 
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)callingPrincipal.Identity).Impersonate(); 

//Insert your code that runs under the security context of the authenticating user here. 

impersonationContext.Undo(); 

hay, có thể được, bạn có thể sử dụng tài khoản .Token, một cái gì đó như thế này:

HostingEnvironment.QueueBackgroundWorkItem(token => 
{ 
    try 
    { 
     _logger.Debug("Executing queued background work item"); 
     using (HostingEnvironment.Impersonate(callingPrincipal.Identity)) 
     { 
      using (var scope = DependencyResolver.BeginLifetimeScope()) 
      { 
       var service = scope.Resolve<T>(); 
       action(service); 
      } 
     } 
     // UNCOMMENT - THROWS EXCEPTION 
     // Thread.CurrentPrincipal = callingPrincipal; 
    } 
    catch (Exception ex) 
    { 
     _logger.Fatal(ex); 
    } 
    finally 
    { 
     _logger.Debug("Completed queued background work item"); 
    } 
}); 

tôi đề nghị bạn xem lại thiết kế kiến ​​trúc của bạn, do đó bạn có thể tìm thấy một cách để di chuyển ra khỏi các hoạt động nền cho bối cảnh khác, trong đó danh tính người dùng sẽ ở lại lâu hơn. cách khác, ví dụ, là sử dụng qua dòng OperationContext đến Task:

// store local operation context 
var operationContext = OperationContext.Current; 
TaskFactory.StartNew(() => 
{ 
    // initialize the current operation context 
    OperationContext.Current = operationContext; 
    action(); 
}) 
+0

OP hoàn toàn khác với mạo danh.Vấn đề OP có là thread chính được xử lý trong khi Background Thread đang xử lý. ** Nó không phải là một thực hành tốt trong ASP.Net ** đó là lý do tại sao Yuval Itzchakov và tôi yêu cầu. Thông thường, chúng tôi lưu trữ dữ liệu trong lưu trữ liên tục như cơ sở dữ liệu trước khi xử lý trong chuỗi nền. – Win

+0

Tôi hiểu vấn đề và cố gắng giải thích cách không liên kết với 'CurrentThread' cho hoạt động lâu dài. – VMAtm

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