Skip to content

Commit

Permalink
Merge pull request #8153 from abpframework/maliming/AbpUserClaimsPrin…
Browse files Browse the repository at this point in the history
…cipalFactory

Refactor AbpUserClaimsPrincipalFactory.
  • Loading branch information
realLiangshiwei committed Mar 22, 2021
2 parents 4ff245e + 36e3cb1 commit c91f025
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,44 @@ public static string FindClientId([NotNull] this IIdentity identity)

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

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace Volo.Abp.Security.Claims
{
public class AbpClaimsPrincipalFactory : IAbpClaimsPrincipalFactory, ITransientDependency
{
public static string AuthenticationType => "Abp.Application";

protected IServiceScopeFactory ServiceScopeFactory { get; }
protected AbpClaimsPrincipalFactoryOptions Options { get; }

Expand All @@ -19,11 +21,14 @@ public class AbpClaimsPrincipalFactory : IAbpClaimsPrincipalFactory, ITransientD
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(new ClaimsIdentity(
AuthenticationType,
AbpClaimTypes.UserName,
AbpClaimTypes.Role));

var context = new AbpClaimsPrincipalContributorContext(claimsPrincipal, scope.ServiceProvider);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Volo.Abp.Security.Claims
{
public interface IAbpClaimsPrincipalFactory
{
Task<ClaimsPrincipal> CreateAsync();
Task<ClaimsPrincipal> CreateAsync(ClaimsPrincipal existsClaimsPrincipal = null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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.Name, ClaimTypes.Role));
claimsPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.Name, "123"));
claimsPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.Role, "admin"));

await _abpClaimsPrincipalFactory.CreateAsync(claimsPrincipal);
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Name && 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;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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;
Expand Down Expand Up @@ -69,11 +70,7 @@ public override async Task<ClaimsPrincipal> CreateAsync(IdentityUser user)

using (CurrentPrincipalAccessor.Change(identity))
{
var abpClaimsPrincipal = await AbpClaimsPrincipalFactory.CreateAsync();
foreach (var claim in abpClaimsPrincipal.Claims)
{
identity.AddIfNotContains(claim);
}
await AbpClaimsPrincipalFactory.CreateAsync(principal);
}

return principal;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using IdentityUser = Volo.Abp.Identity.IdentityUser;

namespace Volo.Abp.IdentityServer.AspNetIdentity
Expand Down

0 comments on commit c91f025

Please sign in to comment.