Browse Source
Merge pull request #10152 from abpframework/maliming/PermissionsRequirementHandler
Add `PermissionsRequirement` and `PermissionsRequirementHandler` to check multiple permissions.
pull/10160/head
liangshiwei
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with
114 additions and
3 deletions
-
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirement.cs
-
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/PermissionsRequirementHandler.cs
-
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/AuthTestController_Tests.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Authorization/TestPermissionDefinitionProvider.cs
-
framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs
|
|
|
@ -0,0 +1,25 @@ |
|
|
|
using JetBrains.Annotations; |
|
|
|
using Microsoft.AspNetCore.Authorization; |
|
|
|
|
|
|
|
namespace Volo.Abp.Authorization |
|
|
|
{ |
|
|
|
public class PermissionsRequirement : IAuthorizationRequirement |
|
|
|
{ |
|
|
|
public string[] PermissionNames { get; } |
|
|
|
|
|
|
|
public bool RequiresAll { get; } |
|
|
|
|
|
|
|
public PermissionsRequirement([NotNull]string[] permissionNames, bool requiresAll) |
|
|
|
{ |
|
|
|
Check.NotNull(permissionNames, nameof(permissionNames)); |
|
|
|
|
|
|
|
PermissionNames = permissionNames; |
|
|
|
RequiresAll = requiresAll; |
|
|
|
} |
|
|
|
|
|
|
|
public override string ToString() |
|
|
|
{ |
|
|
|
return $"PermissionsRequirement: {string.Join(", ", PermissionNames)}"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -0,0 +1,31 @@ |
|
|
|
using System.Linq; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.AspNetCore.Authorization; |
|
|
|
using Volo.Abp.Authorization.Permissions; |
|
|
|
|
|
|
|
namespace Volo.Abp.Authorization |
|
|
|
{ |
|
|
|
public class PermissionsRequirementHandler : AuthorizationHandler<PermissionsRequirement> |
|
|
|
{ |
|
|
|
private readonly IPermissionChecker _permissionChecker; |
|
|
|
|
|
|
|
public PermissionsRequirementHandler(IPermissionChecker permissionChecker) |
|
|
|
{ |
|
|
|
_permissionChecker = permissionChecker; |
|
|
|
} |
|
|
|
|
|
|
|
protected override async Task HandleRequirementAsync( |
|
|
|
AuthorizationHandlerContext context, |
|
|
|
PermissionsRequirement requirement) |
|
|
|
{ |
|
|
|
var multiplePermissionGrantResult = await _permissionChecker.IsGrantedAsync(context.User, requirement.PermissionNames); |
|
|
|
|
|
|
|
if (requirement.RequiresAll ? |
|
|
|
multiplePermissionGrantResult.AllGranted : |
|
|
|
multiplePermissionGrantResult.Result.Any(x => x.Value == PermissionGrantResult.Granted)) |
|
|
|
{ |
|
|
|
context.Succeed(requirement); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -31,6 +31,7 @@ namespace Volo.Abp.Authorization |
|
|
|
context.Services.AddAuthorizationCore(); |
|
|
|
|
|
|
|
context.Services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>(); |
|
|
|
context.Services.AddSingleton<IAuthorizationHandler, PermissionsRequirementHandler>(); |
|
|
|
|
|
|
|
context.Services.TryAddTransient<DefaultAuthorizationPolicyProvider>(); |
|
|
|
|
|
|
|
|
|
|
|
@ -11,6 +11,7 @@ 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.Authorization; |
|
|
|
using Volo.Abp.Autofac; |
|
|
|
using Volo.Abp.GlobalFeatures; |
|
|
|
using Volo.Abp.Localization; |
|
|
|
@ -65,6 +66,16 @@ namespace Volo.Abp.AspNetCore.Mvc |
|
|
|
{ |
|
|
|
policy.RequireClaim("MyCustomClaimType", "42"); |
|
|
|
}); |
|
|
|
|
|
|
|
options.AddPolicy("TestPermission1_And_TestPermission2", policy => |
|
|
|
{ |
|
|
|
policy.Requirements.Add(new PermissionsRequirement(new []{"TestPermission1", "TestPermission2"}, requiresAll: true)); |
|
|
|
}); |
|
|
|
|
|
|
|
options.AddPolicy("TestPermission1_Or_TestPermission2", policy => |
|
|
|
{ |
|
|
|
policy.Requirements.Add(new PermissionsRequirement(new []{"TestPermission1", "TestPermission2"}, requiresAll: false)); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
Configure<AbpAspNetCoreMvcOptions>(options => |
|
|
|
|
|
|
|
@ -38,5 +38,19 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization |
|
|
|
CurrentUser.Id.ShouldBe(FakeUserId); |
|
|
|
return Content("OK"); |
|
|
|
} |
|
|
|
|
|
|
|
[Authorize("TestPermission1_And_TestPermission2")] |
|
|
|
public ActionResult Custom_And_PolicyTest() |
|
|
|
{ |
|
|
|
CurrentUser.Id.ShouldBe(FakeUserId); |
|
|
|
return Content("OK"); |
|
|
|
} |
|
|
|
|
|
|
|
[Authorize("TestPermission1_Or_TestPermission2")] |
|
|
|
public ActionResult Custom_Or_PolicyTest() |
|
|
|
{ |
|
|
|
CurrentUser.Id.ShouldBe(FakeUserId); |
|
|
|
return Content("OK"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -1,5 +1,4 @@ |
|
|
|
using System; |
|
|
|
using System.Net; |
|
|
|
using System.Net; |
|
|
|
using System.Security.Claims; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Shouldly; |
|
|
|
@ -72,5 +71,29 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization |
|
|
|
var result = await GetResponseAsStringAsync("/AuthTest/PermissionTest"); |
|
|
|
result.ShouldBe("OK"); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Custom_And_Policy_Should_Not_Work_When_Permissions_Not_Granted() |
|
|
|
{ |
|
|
|
_fakeRequiredService.Claims.AddRange(new[] |
|
|
|
{ |
|
|
|
new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString()) |
|
|
|
}); |
|
|
|
|
|
|
|
var response = await GetResponseAsync("/AuthTest/Custom_And_PolicyTest", HttpStatusCode.Forbidden, xmlHttpRequest: true); |
|
|
|
response.StatusCode.ShouldBe(HttpStatusCode.Forbidden); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Custom_Or_Policy_Should_Work_When_Permissions_Are_Granted() |
|
|
|
{ |
|
|
|
_fakeRequiredService.Claims.AddRange(new[] |
|
|
|
{ |
|
|
|
new Claim(AbpClaimTypes.UserId, AuthTestController.FakeUserId.ToString()) |
|
|
|
}); |
|
|
|
|
|
|
|
var result = await GetResponseAsStringAsync("/AuthTest/Custom_Or_PolicyTest"); |
|
|
|
result.ShouldBe("OK"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -9,6 +9,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Authorization |
|
|
|
var testGroup = context.AddGroup("TestGroup"); |
|
|
|
|
|
|
|
testGroup.AddPermission("TestPermission1"); |
|
|
|
testGroup.AddPermission("TestPermission2"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -3,6 +3,7 @@ using System.Net; |
|
|
|
using System.Net.Http; |
|
|
|
using System.Text.Json; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.Net.Http.Headers; |
|
|
|
using Shouldly; |
|
|
|
using Volo.Abp.AspNetCore.TestBase; |
|
|
|
|
|
|
|
@ -30,11 +31,15 @@ namespace Volo.Abp.AspNetCore |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<HttpResponseMessage> GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK) |
|
|
|
protected virtual async Task<HttpResponseMessage> GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, bool xmlHttpRequest = false) |
|
|
|
{ |
|
|
|
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url)) |
|
|
|
{ |
|
|
|
requestMessage.Headers.Add("Accept-Language", CultureInfo.CurrentUICulture.Name); |
|
|
|
if (xmlHttpRequest) |
|
|
|
{ |
|
|
|
requestMessage.Headers.Add(HeaderNames.XRequestedWith, "XMLHttpRequest"); |
|
|
|
} |
|
|
|
var response = await Client.SendAsync(requestMessage); |
|
|
|
response.StatusCode.ShouldBe(expectedStatusCode); |
|
|
|
return response; |
|
|
|
|