Saving a principal inside a given working background

I am using ASP.Net Web API 2 / .Net 4.5.2.

I am trying to keep the caller principal while queuing background work. To this end, I try:

Thread.CurrentPrincipal = callingPrincipal; 

But when I do this, I get an ObjectDisposedException:

System.ObjectDisposedException: secure handle closed

How to keep the current director in the background?
Can I make a copy of the principal in some way?

 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"); } }); } 
+5
source share
2 answers

Turns ClaimsPrincipal now has a copy constructor.

 var principal = new ClaimsPrincipal(Thread.CurrentPrincipal); 

This seems to fix the problem, while preserving all the information about the person and the claims. Full function:

 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"); } }); } 
+5
source

The problem with your situation is that the background task runs after Thread.CurrentPrincipal . This is due to the ASP.NET model โ€” the request is processed in the user context, and after that all values โ€‹โ€‹corresponding to the user are freed. So this is definitely happening to your personality. Try to save information about the user and his identity, then to impersonate him.

You can view the Microsoft support article for impersonating operations on ASP.NET sites, but I don't think this will be useful to you:

 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(); 

or maybe you can use User.Token, something like this:

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

I suggest you look at the design of your architecture so that you can find a way to move the background operation to a different context in which the user ID will remain longer. Another way, for example, is to use passing the current OperationContext to the Task :

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

Source: https://habr.com/ru/post/1243232/


All Articles