Browse Source
Restore the previous ambient principal when a Change scope is disposed
pull/25752/head
maliming
3 months ago
No known key found for this signature in database
GPG Key ID: A646B9CB645ECEA4
2 changed files with
39 additions and
3 deletions
-
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/CurrentPrincipalAccessorBase.cs
-
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/CurrentPrincipalAccessor_Tests.cs
|
|
|
@ -8,7 +8,7 @@ public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor |
|
|
|
{ |
|
|
|
public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); |
|
|
|
|
|
|
|
private readonly AsyncLocal<ClaimsPrincipal> _currentPrincipal = new AsyncLocal<ClaimsPrincipal>(); |
|
|
|
private readonly AsyncLocal<ClaimsPrincipal?> _currentPrincipal = new AsyncLocal<ClaimsPrincipal?>(); |
|
|
|
|
|
|
|
protected abstract ClaimsPrincipal GetClaimsPrincipal(); |
|
|
|
|
|
|
|
@ -19,10 +19,10 @@ public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor |
|
|
|
|
|
|
|
private IDisposable SetCurrent(ClaimsPrincipal principal) |
|
|
|
{ |
|
|
|
var parent = Principal; |
|
|
|
var parent = _currentPrincipal.Value; |
|
|
|
_currentPrincipal.Value = principal; |
|
|
|
|
|
|
|
return new DisposeAction<ValueTuple<AsyncLocal<ClaimsPrincipal>, ClaimsPrincipal>>(static (state) => |
|
|
|
return new DisposeAction<ValueTuple<AsyncLocal<ClaimsPrincipal?>, ClaimsPrincipal?>>(static (state) => |
|
|
|
{ |
|
|
|
var (currentPrincipal, parent) = state; |
|
|
|
currentPrincipal.Value = parent; |
|
|
|
|
|
|
|
@ -52,4 +52,40 @@ public class CurrentPrincipalAccessor_Tests : AbpIntegratedTest<AbpSecurityTestM |
|
|
|
currentPrincipal.Identity.ShouldNotBeNull(); |
|
|
|
currentPrincipal.Identity.IsAuthenticated.ShouldBeFalse(); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Should_Reflect_Underlying_Source_After_Change_Scope_Disposed() |
|
|
|
{ |
|
|
|
var accessor = new TestCurrentPrincipalAccessor(); |
|
|
|
|
|
|
|
var changedPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> |
|
|
|
{ |
|
|
|
new Claim(ClaimTypes.NameIdentifier, "123456") |
|
|
|
})); |
|
|
|
|
|
|
|
using (accessor.Change(changedPrincipal)) |
|
|
|
{ |
|
|
|
accessor.Principal.ShouldBe(changedPrincipal); |
|
|
|
} |
|
|
|
|
|
|
|
// Disposing the Change scope must not pin the accessor to the fallback principal;
|
|
|
|
// a principal that becomes available afterwards has to be reflected.
|
|
|
|
var sourcePrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim> |
|
|
|
{ |
|
|
|
new Claim(ClaimTypes.NameIdentifier, "654321") |
|
|
|
})); |
|
|
|
accessor.SourcePrincipal = sourcePrincipal; |
|
|
|
|
|
|
|
accessor.Principal.ShouldBe(sourcePrincipal); |
|
|
|
} |
|
|
|
|
|
|
|
private class TestCurrentPrincipalAccessor : CurrentPrincipalAccessorBase |
|
|
|
{ |
|
|
|
public ClaimsPrincipal? SourcePrincipal { get; set; } |
|
|
|
|
|
|
|
protected override ClaimsPrincipal GetClaimsPrincipal() |
|
|
|
{ |
|
|
|
return SourcePrincipal ?? new ClaimsPrincipal(new ClaimsIdentity()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|