without practices pattern method false configureawait best await async async-await claims-based-identity synchronizationcontext executioncontext current-principal

async-await - practices - call async method c# await



Seguridad, Thread.CurrentPrincipal y ConfigureAwait(falso) (1)

Según mis pruebas, parece que Thread.CurrentPrincipal fluirá correctamente, incluso si usa ConfigureAwait(false) . El siguiente código WebAPI establece el principal y luego bloquea en una llamada async , lo que obliga a otro hilo a reanudar el método async . Ese otro hilo hereda el principal correcto.

private async Task<string> Async() { await Task.Delay(1000).ConfigureAwait(false); return "Thread " + Thread.CurrentThread.ManagedThreadId + ": " + Thread.CurrentPrincipal.Identity.Name + "/n"; } public string Get(int id) { var user = new ClaimsPrincipal(new ClaimsIdentity( new[] { new Claim(ClaimTypes.Name, "Bob"), } )); HttpContext.Current.User = user; Thread.CurrentPrincipal = user; var ret = "Thread " + Thread.CurrentThread.ManagedThreadId + ": " + Thread.CurrentPrincipal.Identity.Name + "/n"; ret += Async().Result; return ret; }

Cuando ejecuto este código en una nueva instancia de IISExpress, obtengo:

"Thread 7: Bob/nThread 6: Bob/n"

Sin embargo, debo señalar que no se recomienda usar ConfigureAwait(false) para evitar el interbloqueo. Esto es especialmente cierto en ASP.NET. Si es posible, use ConfigureAwait(false) y también use async hasta el final. Tenga en cuenta que WebAPI es una pila totalmente async y debería poder hacer esto.

¿El uso de las afirmaciones de Thread.CurrentPrincipal en una biblioteca referenciada que utiliza ConfigureAwait (falso) plantea algún problema o el flujo del contexto de llamada lógica de ExecutionContext me ocupará allí? (mi lectura y prueba hasta el momento indican que sí).

Ejemplo de acción del controlador WebAPI:

[CustomAuthorizeThatSetsCurrentUsersClaimsToThreadCurrentContextAndHttpContextCurrentUser] public async Task<Order> Get(int orderId) { return await _orderBusinessLogicLibrary.LoadAsync(orderId); // defaults to .ConfigureAwait(true) }

Ejemplo de funciones de carga desde una biblioteca externa referenciada:

[ClaimsPrincipalPermission( SecurityAction.Demand, Operation="Read", Resource="Orders")] [ClaimsPrincipalPermission( SecurityAction.Demand, Operation="Read", Resource="OrderItems")] public async Task<Order> Load(int orderId) { var order = await _repository.LoadOrderAsync(orderId).ConfigureAwait(false); // here''s the key line.. assuming this lower-level function is also imposing // security constraints in the same way this method does, would // Thread.CurrentPrincipal still be correct inside the function below? order.Items = await _repository.LoadOrderItemsAsync(orderId).ConfigureAwait(false); return order; }

Además, la respuesta no puede ser "¡bueno, no uses ConfigureAwait (falso)!". Eso puede causar otros problemas, como interbloqueo ( No bloquear en código Async ).