Browse Source

Refactor AbpUserClaimsPrincipalFactory.

Resolve #8115
pull/8153/head
maliming 6 years ago
parent
commit
11894f27d9
  1. 39
      framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs
  2. 4
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs
  3. 21
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ClaimsIdentityExtensions.cs
  4. 2
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs
  5. 1
      framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj
  6. 6
      framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/AbpSecurityTestModule.cs
  7. 104
      framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs
  8. 7
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory.cs
  9. 64
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs

39
framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs

@ -122,5 +122,44 @@ namespace System.Security.Principal
return Guid.Parse(editionIdOrNull.Value);
}
public static ClaimsIdentity AddIfNotContains(this ClaimsIdentity claimsIdentity, Claim claim)
{
Check.NotNull(claimsIdentity, nameof(claimsIdentity));
if (!claimsIdentity.Claims.Any(x => string.Equals(x.Type, claim.Type, StringComparison.OrdinalIgnoreCase)))
{
claimsIdentity.AddClaim(claim);
}
return claimsIdentity;
}
public static ClaimsIdentity AddOrReplace(this ClaimsIdentity claimsIdentity, Claim claim)
{
Check.NotNull(claimsIdentity, nameof(claimsIdentity));
foreach (var x in claimsIdentity.FindAll(claim.Type).ToList())
{
claimsIdentity.RemoveClaim(x);
}
claimsIdentity.AddClaim(claim);
return claimsIdentity;
}
public static ClaimsPrincipal AddIdentityIfNotContains([NotNull] this ClaimsPrincipal principal, ClaimsIdentity identity)
{
Check.NotNull(principal, nameof(principal));
if (!principal.Identities.Any(x => string.Equals(x.AuthenticationType, identity.AuthenticationType, StringComparison.OrdinalIgnoreCase)))
{
principal.AddIdentity(identity);
}
return principal;
}
}
}

4
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory.cs

@ -19,11 +19,11 @@ namespace Volo.Abp.Security.Claims
Options = abpClaimOptions.Value;
}
public virtual async Task<ClaimsPrincipal> CreateAsync()
public virtual async Task<ClaimsPrincipal> CreateAsync(ClaimsPrincipal existsClaimsPrincipal = null)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity());
var claimsPrincipal = existsClaimsPrincipal ?? new ClaimsPrincipal();
var context = new AbpClaimsPrincipalContributorContext(claimsPrincipal, scope.ServiceProvider);

21
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/ClaimsIdentityExtensions.cs

@ -1,21 +0,0 @@
using System;
using System.Linq;
using System.Security.Claims;
namespace Volo.Abp.Security.Claims
{
public static class ClaimsIdentityExtensions
{
public static ClaimsIdentity AddIfNotContains(this ClaimsIdentity claimsIdentity, Claim claim)
{
if (!claimsIdentity.Claims.Any(existClaim =>
existClaim != null &&
string.Equals(existClaim.Type, claim.Type, StringComparison.OrdinalIgnoreCase)))
{
claimsIdentity.AddClaim(claim);
}
return claimsIdentity;
}
}
}

2
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/IAbpClaimsPrincipalFactory.cs

@ -5,6 +5,6 @@ namespace Volo.Abp.Security.Claims
{
public interface IAbpClaimsPrincipalFactory
{
Task<ClaimsPrincipal> CreateAsync();
Task<ClaimsPrincipal> CreateAsync(ClaimsPrincipal existsClaimsPrincipal = null);
}
}

1
framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj

@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />

6
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/AbpSecurityTestModule.cs

@ -1,11 +1,13 @@
using Volo.Abp.Modularity;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.SecurityLog;
namespace Volo.Abp.Security
{
[DependsOn(
typeof(AbpSecurityModule),
typeof(AbpTestBaseModule)
typeof(AbpTestBaseModule),
typeof(AbpAutofacModule)
)]
public class AbpSecurityTestModule : AbpModule
{

104
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Claims/AbpClaimsPrincipalFactory_Test.cs

@ -0,0 +1,104 @@
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Testing;
using Xunit;
namespace Volo.Abp.Security.Claims
{
public class AbpClaimsPrincipalFactory_Test : AbpIntegratedTest<AbpSecurityTestModule>
{
private readonly IAbpClaimsPrincipalFactory _abpClaimsPrincipalFactory;
private static string TestAuthenticationType => "Identity.Application";
public AbpClaimsPrincipalFactory_Test()
{
_abpClaimsPrincipalFactory = GetRequiredService<IAbpClaimsPrincipalFactory>();
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected override void AfterAddApplication(IServiceCollection services)
{
services.AddTransient<TestAbpClaimsPrincipalContributor>();
services.AddTransient<Test2AbpClaimsPrincipalContributor>();
services.AddTransient<Test3AbpClaimsPrincipalContributor>();
}
[Fact]
public async Task CreateAsync()
{
var claimsPrincipal = await _abpClaimsPrincipalFactory.CreateAsync();
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Email && x.Value == "admin2@abp.io");
claimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Email && x.Value == "admin@abp.io");
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Version && x.Value == "2.0");
}
[Fact]
public async Task Create_With_Exists_ClaimsPrincipal()
{
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(TestAuthenticationType, ClaimTypes.NameIdentifier, ClaimTypes.Role));
claimsPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.NameIdentifier, "123"));
claimsPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.Role, "admin"));
await _abpClaimsPrincipalFactory.CreateAsync(claimsPrincipal);
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.NameIdentifier && x.Value == "123");
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "admin");
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Email && x.Value == "admin2@abp.io");
claimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Email && x.Value == "admin@abp.io");
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Version && x.Value == "2.0");
}
class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor
{
public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType)
?? new ClaimsIdentity(TestAuthenticationType);
claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Email, "admin@abp.io"));
context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity);
return Task.CompletedTask;
}
}
class Test2AbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor
{
public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType)
?? new ClaimsIdentity(TestAuthenticationType);
claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Email, "admin2@abp.io"));
context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity);
return Task.CompletedTask;
}
}
class Test3AbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor
{
public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var claimsIdentity = context.ClaimsPrincipal.Identities.FirstOrDefault(x => x.AuthenticationType == TestAuthenticationType)
?? new ClaimsIdentity(TestAuthenticationType);
claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Version, "2.0"));
context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity);
return Task.CompletedTask;
}
}
}
}

7
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory.cs

@ -4,6 +4,7 @@ using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Security.Principal;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
@ -69,11 +70,7 @@ namespace Volo.Abp.Identity
using (CurrentPrincipalAccessor.Change(identity))
{
var abpClaimsPrincipal = await AbpClaimsPrincipalFactory.CreateAsync();
foreach (var claim in abpClaimsPrincipal.Claims)
{
identity.AddIfNotContains(claim);
}
await AbpClaimsPrincipalFactory.CreateAsync(principal);
}
return principal;

64
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpUserClaimsPrincipalFactory_Tests.cs

@ -0,0 +1,64 @@
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Xunit;
namespace Volo.Abp.Identity
{
public class AbpUserClaimsPrincipalFactory_Tests : AbpIdentityDomainTestBase
{
private readonly IdentityUserManager _identityUserManager;
private readonly AbpUserClaimsPrincipalFactory _abpUserClaimsPrincipalFactory;
private readonly IdentityTestData _testData;
public AbpUserClaimsPrincipalFactory_Tests()
{
_identityUserManager = GetRequiredService<IdentityUserManager>();
_abpUserClaimsPrincipalFactory = GetRequiredService<AbpUserClaimsPrincipalFactory>();
_testData = GetRequiredService<IdentityTestData>();
}
[Fact]
public async Task Add_And_Replace_Claims_Test()
{
await UsingUowAsync(async () =>
{
var user = await _identityUserManager.GetByIdAsync(_testData.UserJohnId);
user.ShouldNotBeNull();
var claimsPrincipal = await _abpUserClaimsPrincipalFactory.CreateAsync(user);
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.NameIdentifier && x.Value == user.Id.ToString());
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Name && x.Value == user.UserName);
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Uri && x.Value =="www.abp.io");
claimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Email && x.Value == user.Email);
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Email && x.Value == "replaced@abp.io");
});
}
class TestAbpClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
{
//https://github.com/dotnet/aspnetcore/blob/v5.0.0/src/Identity/Extensions.Core/src/UserClaimsPrincipalFactory.cs#L79
private static string IdentityAuthenticationType => "Identity.Application";
public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var claimsIdentity = context.ClaimsPrincipal.Identities.First(x => x.AuthenticationType == IdentityAuthenticationType);
claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Uri, "www.abp.io"));
claimsIdentity.AddOrReplace(new Claim(ClaimTypes.Email, "replaced@abp.io"));
context.ClaimsPrincipal.AddIdentityIfNotContains(claimsIdentity);
return Task.CompletedTask;
}
}
}
}
Loading…
Cancel
Save