mirror of https://github.com/abpframework/abp.git
17 changed files with 401 additions and 29 deletions
@ -0,0 +1,17 @@ |
|||
namespace Volo.Abp.AspNetCore.ExceptionHandling |
|||
{ |
|||
public class AbpAuthorizationExceptionHandlerOptions |
|||
{ |
|||
public bool UseAuthenticationScheme { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Use default forbid/challenge scheme if this is not specified.
|
|||
/// </summary>
|
|||
public string AuthenticationScheme { get; set; } |
|||
|
|||
public AbpAuthorizationExceptionHandlerOptions() |
|||
{ |
|||
UseAuthenticationScheme = true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.ExceptionHandling |
|||
{ |
|||
public class DefaultAbpAuthorizationExceptionHandler : IAbpAuthorizationExceptionHandler, ITransientDependency |
|||
{ |
|||
public virtual async Task<bool> HandleAsync(AbpAuthorizationException exception, HttpContext httpContext) |
|||
{ |
|||
var isAuthenticated = httpContext.User.Identity?.IsAuthenticated ?? false; |
|||
|
|||
var handlerOptions = httpContext.RequestServices.GetRequiredService<IOptions<AbpAuthorizationExceptionHandlerOptions>>().Value; |
|||
if (handlerOptions.UseAuthenticationScheme) |
|||
{ |
|||
var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>(); |
|||
|
|||
if (!handlerOptions.AuthenticationScheme.IsNullOrWhiteSpace()) |
|||
{ |
|||
var handler = await handlers.GetHandlerAsync(httpContext, handlerOptions.AuthenticationScheme); |
|||
if (handler != null) |
|||
{ |
|||
if (isAuthenticated) |
|||
{ |
|||
await handler.ForbidAsync(null); |
|||
} |
|||
else |
|||
{ |
|||
await handler.ChallengeAsync(null); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
var authenticationSchemeProvider = httpContext.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>(); |
|||
var scheme = isAuthenticated |
|||
? await authenticationSchemeProvider.GetDefaultForbidSchemeAsync() |
|||
: await authenticationSchemeProvider.GetDefaultChallengeSchemeAsync(); |
|||
|
|||
if (scheme != null) |
|||
{ |
|||
var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name); |
|||
if (handler != null) |
|||
{ |
|||
if (isAuthenticated) |
|||
{ |
|||
await handler.ForbidAsync(null); |
|||
} |
|||
else |
|||
{ |
|||
await handler.ChallengeAsync(null); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.Authorization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.ExceptionHandling |
|||
{ |
|||
public interface IAbpAuthorizationExceptionHandler |
|||
{ |
|||
Task<bool> HandleAsync(AbpAuthorizationException exception, HttpContext httpContext); |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using System; |
|||
using System.Net; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using NSubstitute; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.ExceptionHandling; |
|||
using Volo.Abp.ExceptionHandling; |
|||
using Volo.Abp.Security.Claims; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling |
|||
{ |
|||
public class AbpAuthorizationExceptionTestController_Tests : AspNetCoreMvcTestBase |
|||
{ |
|||
protected IExceptionSubscriber FakeExceptionSubscriber; |
|||
|
|||
protected FakeUserClaims FakeRequiredService; |
|||
|
|||
public AbpAuthorizationExceptionTestController_Tests() |
|||
{ |
|||
FakeRequiredService = GetRequiredService<FakeUserClaims>(); |
|||
} |
|||
|
|||
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) |
|||
{ |
|||
base.ConfigureServices(context, services); |
|||
|
|||
FakeExceptionSubscriber = Substitute.For<IExceptionSubscriber>(); |
|||
|
|||
services.AddSingleton(FakeExceptionSubscriber); |
|||
|
|||
services.Configure<AbpAuthorizationExceptionHandlerOptions>(options => |
|||
{ |
|||
options.UseAuthenticationScheme = true; |
|||
options.AuthenticationScheme = "Cookie"; |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public virtual async Task Should_Handle_By_Cookie_AuthenticationScheme_For_AbpAuthorizationException() |
|||
{ |
|||
var result = await GetResponseAsync("/api/exception-test/AbpAuthorizationException", HttpStatusCode.Redirect); |
|||
result.Headers.Location.ToString().ShouldContain("http://localhost/Account/Login"); |
|||
|
|||
#pragma warning disable 4014
|
|||
FakeExceptionSubscriber |
|||
.Received() |
|||
.HandleAsync(Arg.Any<ExceptionNotificationContext>()); |
|||
#pragma warning restore 4014
|
|||
|
|||
|
|||
FakeRequiredService.Claims.AddRange(new[] |
|||
{ |
|||
new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()) |
|||
}); |
|||
|
|||
result = await GetResponseAsync("/api/exception-test/AbpAuthorizationException", HttpStatusCode.Redirect); |
|||
result.Headers.Location.ToString().ShouldContain("http://localhost/Account/AccessDenied"); |
|||
|
|||
#pragma warning disable 4014
|
|||
FakeExceptionSubscriber |
|||
.Received() |
|||
.HandleAsync(Arg.Any<ExceptionNotificationContext>()); |
|||
#pragma warning restore 4014
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using System; |
|||
using System.Net; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using NSubstitute; |
|||
using Shouldly; |
|||
using Volo.Abp.AspNetCore.ExceptionHandling; |
|||
using Volo.Abp.ExceptionHandling; |
|||
using Volo.Abp.Security.Claims; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling |
|||
{ |
|||
public class AbpAuthorizationExceptionTestPage_Tests : AspNetCoreMvcTestBase |
|||
{ |
|||
private IExceptionSubscriber _fakeExceptionSubscriber; |
|||
|
|||
private FakeUserClaims _fakeRequiredService; |
|||
|
|||
public AbpAuthorizationExceptionTestPage_Tests() |
|||
{ |
|||
_fakeRequiredService = GetRequiredService<FakeUserClaims>(); |
|||
} |
|||
|
|||
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) |
|||
{ |
|||
base.ConfigureServices(context, services); |
|||
|
|||
_fakeExceptionSubscriber = Substitute.For<IExceptionSubscriber>(); |
|||
|
|||
services.AddSingleton(_fakeExceptionSubscriber); |
|||
|
|||
services.Configure<AbpAuthorizationExceptionHandlerOptions>(options => |
|||
{ |
|||
options.UseAuthenticationScheme = true; |
|||
options.AuthenticationScheme = "Cookie"; |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public virtual async Task Should_Handle_By_Cookie_AuthenticationScheme_For_AbpAuthorizationException() |
|||
{ |
|||
var result = await GetResponseAsync("/ExceptionHandling/ExceptionTestPage?handler=AbpAuthorizationException", HttpStatusCode.Redirect); |
|||
result.Headers.Location.ToString().ShouldContain("http://localhost/Account/Login"); |
|||
|
|||
#pragma warning disable 4014
|
|||
_fakeExceptionSubscriber |
|||
.Received() |
|||
.HandleAsync(Arg.Any<ExceptionNotificationContext>()); |
|||
#pragma warning restore 4014
|
|||
|
|||
|
|||
_fakeRequiredService.Claims.AddRange(new[] |
|||
{ |
|||
new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()) |
|||
}); |
|||
|
|||
result = await GetResponseAsync("/ExceptionHandling/ExceptionTestPage?handler=AbpAuthorizationException", HttpStatusCode.Redirect); |
|||
result.Headers.Location.ToString().ShouldContain("http://localhost/Account/AccessDenied"); |
|||
|
|||
#pragma warning disable 4014
|
|||
_fakeExceptionSubscriber |
|||
.Received() |
|||
.HandleAsync(Arg.Any<ExceptionNotificationContext>()); |
|||
#pragma warning restore 4014
|
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue