{
[ThreadStatic]
private static Thread t_currentThread;
+ private static AsyncLocal<IPrincipal> s_asyncLocalPrincipal;
private readonly RuntimeThread _runtimeThread;
private Delegate _start;
private CultureInfo _startCulture;
private CultureInfo _startUICulture;
- private IPrincipal _principal;
private Thread(RuntimeThread runtimeThread)
{
{
get
{
- return CurrentThread._principal ?? (CurrentThread._principal = AppDomain.CurrentDomain.GetThreadPrincipal());
+ if (s_asyncLocalPrincipal is null)
+ {
+ CurrentPrincipal = AppDomain.CurrentDomain.GetThreadPrincipal();
+ }
+ return s_asyncLocalPrincipal?.Value;
}
set
{
- CurrentThread._principal = value;
+ if (s_asyncLocalPrincipal is null)
+ {
+ if (value is null)
+ {
+ return;
+ }
+ Interlocked.CompareExchange(ref s_asyncLocalPrincipal, new AsyncLocal<IPrincipal>(), null);
+ }
+ s_asyncLocalPrincipal.Value = value;
}
}
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Security.Claims;
using System.Security.Principal;
+using System.Threading.Tasks;
using System.Threading.Tests;
using Xunit;
}
[Fact]
+ public static void CurrentPrincipalContextFlowTest()
+ {
+ ThreadTestHelpers.RunTestInBackgroundThread(async () =>
+ {
+ Thread.CurrentPrincipal = new ClaimsPrincipal();
+
+ await Task.Run(async() => {
+
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+
+ await Task.Run(async() =>
+ {
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+
+ Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("name"), new string[0]);
+
+ await Task.Run(() =>
+ {
+ Assert.IsType<GenericPrincipal>(Thread.CurrentPrincipal);
+ });
+
+ Assert.IsType<GenericPrincipal>(Thread.CurrentPrincipal);
+ });
+
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+ });
+
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+ });
+ }
+
+ [Fact]
+ public static void CurrentPrincipalContextFlowTest_NotFlow()
+ {
+ ThreadTestHelpers.RunTestInBackgroundThread(async () =>
+ {
+ Thread.CurrentPrincipal = new ClaimsPrincipal();
+
+ Task task;
+ using(ExecutionContext.SuppressFlow())
+ {
+ Assert.True(ExecutionContext.IsFlowSuppressed());
+
+ task = Task.Run(() =>
+ {
+ // Default PrincipalPolicy for netcoreapp is null
+ if (PlatformDetection.IsNetCore)
+ {
+ Assert.Null(Thread.CurrentPrincipal);
+ }
+ else
+ {
+ Assert.IsType<GenericPrincipal>(Thread.CurrentPrincipal);
+ }
+
+ Assert.False(ExecutionContext.IsFlowSuppressed());
+ });
+ }
+
+ Assert.False(ExecutionContext.IsFlowSuppressed());
+
+ await task;
+ });
+ }
+
+ [Fact]
+ public static void CurrentPrincipal_SetNull()
+ {
+ // We run test on remote process because we need to set same principal policy
+ // On netfx default principal policy is PrincipalPolicy.UnauthenticatedPrincipal
+ DummyClass.RemoteInvoke(() =>
+ {
+ AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.NoPrincipal);
+
+ Assert.Null(Thread.CurrentPrincipal);
+
+ Thread.CurrentPrincipal = null;
+ Assert.Null(Thread.CurrentPrincipal);
+
+ Thread.CurrentPrincipal = new ClaimsPrincipal();
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+
+ Thread.CurrentPrincipal = null;
+ Assert.Null(Thread.CurrentPrincipal);
+
+ Thread.CurrentPrincipal = new ClaimsPrincipal();
+ Assert.IsType<ClaimsPrincipal>(Thread.CurrentPrincipal);
+ }).Dispose();
+ }
+
+ [Fact]
public static void CurrentThreadTest()
{
Thread otherThread = null;