From b70497eb6c6c03e692f5e186d38333b4258ed92c Mon Sep 17 00:00:00 2001 From: maliming <6908465+maliming@users.noreply.github.com> Date: Sun, 17 May 2020 22:39:10 +0800 Subject: [PATCH] Add AbpClaimsMapMiddleware. Resolve #3975 --- .../AbpApplicationBuilderExtensions.cs | 10 ++++- .../Security/Claims/AbpClaimsMapMiddleware.cs | 29 +++++++++++++ .../Security/Claims/AbpClaimsMapOptions.cs | 14 +++++++ .../Mvc/AbpAspNetCoreMvcTestModule.cs | 13 +++++- .../Claims/ClaimsMapTestController.cs | 22 ++++++++++ .../Claims/ClaimsMapTestController_Tests.cs | 41 +++++++++++++++++++ 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs create mode 100644 framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapOptions.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController.cs create mode 100644 framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs index 295a8bd100..568ecfef7b 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using JetBrains.Annotations; using Microsoft.AspNetCore.RequestLocalization; using Microsoft.Extensions.DependencyInjection; @@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting; using Volo.Abp; using Volo.Abp.AspNetCore.Auditing; using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.Tracing; using Volo.Abp.AspNetCore.Uow; using Volo.Abp.DependencyInjection; @@ -76,5 +77,10 @@ namespace Microsoft.AspNetCore.Builder app.Properties[ExceptionHandlingMiddlewareMarker] = true; return app.UseMiddleware(); } + + public static IApplicationBuilder UseAbpClaimsMap(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs new file mode 100644 index 0000000000..2f2c0af116 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs @@ -0,0 +1,29 @@ +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Security.Claims +{ + public class AbpClaimsMapMiddleware : IMiddleware, ITransientDependency + { + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + var currentPrincipalAccessor = context.RequestServices.GetRequiredService(); + var mapOptions = context.RequestServices.GetRequiredService>().Value; + + var mapClaims = currentPrincipalAccessor.Principal.Claims.Where(p => mapOptions.Map.Keys.Contains(p.Type)); + currentPrincipalAccessor.Principal.AddIdentity(new ClaimsIdentity(mapClaims.Select(p => new Claim( + mapOptions.Map[p.Type], + p.Value, + p.ValueType, + p.Issuer)))); + + await next(context); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapOptions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapOptions.cs new file mode 100644 index 0000000000..b7855df497 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapOptions.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Volo.Abp.AspNetCore.Security.Claims +{ + public class AbpClaimsMapOptions + { + public Dictionary Map { get; } + + public AbpClaimsMapOptions() + { + Map = new Dictionary(); + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs index 90930abc6d..ead51147c9 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc.ApplicationModels; @@ -8,11 +10,13 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.Authorization; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.Localization.Resource; +using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.TestBase; using Volo.Abp.Autofac; using Volo.Abp.Localization; using Volo.Abp.MemoryDb; using Volo.Abp.Modularity; +using Volo.Abp.Security.Claims; using Volo.Abp.TestApp; using Volo.Abp.Validation.Localization; using Volo.Abp.VirtualFileSystem; @@ -76,11 +80,17 @@ namespace Volo.Abp.AspNetCore.Mvc options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); }); - + Configure(options => { options.RootDirectory = "/Volo/Abp/AspNetCore/Mvc"; }); + + Configure(options => + { + options.Map.Add("SerialNumber", ClaimTypes.SerialNumber); + options.Map.Add("DateOfBirth", ClaimTypes.DateOfBirth); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -92,6 +102,7 @@ namespace Volo.Abp.AspNetCore.Mvc app.UseAbpRequestLocalization(); app.UseRouting(); app.UseMiddleware(); + app.UseAbpClaimsMap(); app.UseAuthorization(); app.UseAuditing(); app.UseUnitOfWork(); diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController.cs new file mode 100644 index 0000000000..d8a4a441fd --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController.cs @@ -0,0 +1,22 @@ +using System.Security.Claims; +using Microsoft.AspNetCore.Mvc; +using Shouldly; + +namespace Volo.Abp.AspNetCore.Mvc.Security.Claims +{ + public class ClaimsMapTestController : AbpController + { + public ActionResult ClaimsMapTest() + { + var serialNumber = CurrentUser.FindClaim(ClaimTypes.SerialNumber); + serialNumber.ShouldNotBeNull(); + serialNumber.Value.ShouldBe("123456"); + + var dateOfBirth = CurrentUser.FindClaim(ClaimTypes.DateOfBirth); + dateOfBirth.ShouldNotBeNull(); + dateOfBirth.Value.ShouldBe("2020"); + + return Content("OK"); + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs new file mode 100644 index 0000000000..154956afdf --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Security/Claims/ClaimsMapTestController_Tests.cs @@ -0,0 +1,41 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.AspNetCore.Mvc.Authorization; +using Volo.Abp.AspNetCore.TestBase; +using Volo.Abp.Autofac; +using Volo.Abp.MemoryDb; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Security.Claims +{ + [DependsOn( + typeof(AbpAspNetCoreTestBaseModule), + typeof(AbpMemoryDbTestModule), + typeof(AbpAspNetCoreMvcModule), + typeof(AbpAutofacModule) + )] + public class ClaimsMapTestController_Tests : AspNetCoreMvcTestBase + { + private readonly FakeUserClaims _fakeRequiredService; + + public ClaimsMapTestController_Tests() + { + _fakeRequiredService = GetRequiredService(); + } + + [Fact] + public async Task Claims_Should_Be_Mapped() + { + _fakeRequiredService.Claims.AddRange(new[] + { + new Claim("SerialNumber", "123456"), + new Claim("DateOfBirth", "2020") + }); + + var result = await GetResponseAsStringAsync("/ClaimsMapTest/ClaimsMapTest"); + result.ShouldBe("OK"); + } + } +}