No-op Authorization middleware for Razor Pages
Workaround for https://github.com/aspnet/AspNetCore/issues/7011
This commit is contained in:
parent
2b7c26a123
commit
f2ee3201ae
|
|
@ -4,6 +4,7 @@
|
|||
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
||||
{
|
||||
// This is used to store the uncombined parts of the final page route
|
||||
// Note: This type name is referenced by name in AuthorizationMiddleware, do not change this without addressing https://github.com/aspnet/AspNetCore/issues/7011
|
||||
internal class PageRouteMetadata
|
||||
{
|
||||
public PageRouteMetadata(string pageRoute, string routeTemplate)
|
||||
|
|
|
|||
|
|
@ -1190,11 +1190,11 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore.InjectedPa
|
|||
public async Task AuthFiltersAppliedToPageModel_AreExecuted()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("/ModelWithAuthFilter");
|
||||
var response = await Client.GetAsync("/Pages/ModelWithAuthFilter");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.Equal("/Login?ReturnUrl=%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
|
||||
Assert.Equal("/Login?ReturnUrl=%2FPages%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class RazorPagesWithEndpointRoutingTest : IClassFixture<MvcTestFixture<RazorPagesWebSite.StartupWithEndpointRouting>>
|
||||
{
|
||||
public RazorPagesWithEndpointRoutingTest(MvcTestFixture<RazorPagesWebSite.StartupWithEndpointRouting> fixture)
|
||||
{
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task Authorize_AppliedUsingConvention_Works()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("/Conventions/AuthFolder");
|
||||
|
||||
// Assert
|
||||
await response.AssertStatusCodeAsync(HttpStatusCode.Redirect);
|
||||
Assert.Equal("/Login?ReturnUrl=%2FConventions%2FAuthFolder", response.Headers.Location.PathAndQuery);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Authorize_AppliedUsingConvention_CanByOverridenByAllowAnonymousAppliedToModel()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("/Conventions/AuthFolder/AnonymousViaModel");
|
||||
|
||||
// Assert
|
||||
await response.AssertStatusCodeAsync(HttpStatusCode.OK);
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("Hello from Anonymous", content.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Authorize_AppliedUsingAttributeOnModel_Works()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("/ModelWithAuthFilter");
|
||||
|
||||
// Assert
|
||||
await response.AssertStatusCodeAsync(HttpStatusCode.Redirect);
|
||||
Assert.Equal("/Login?ReturnUrl=%2FModelWithAuthFilter", response.Headers.Location.PathAndQuery);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Authorize_WithEndpointRouting_WorksForControllers()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetAsync("/AuthorizedAction/Index");
|
||||
|
||||
// Assert
|
||||
await response.AssertStatusCodeAsync(HttpStatusCode.Redirect);
|
||||
Assert.Equal("/Login?ReturnUrl=%2FAuthorizedAction%2FIndex", response.Headers.Location.PathAndQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace RazorPagesWebSite.Controllers
|
||||
{
|
||||
[Route("[controller]/[action]")]
|
||||
[Authorize]
|
||||
public class AuthorizedActionController : Controller
|
||||
{
|
||||
public IActionResult Index() => Ok();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace RazorPagesWebSite
|
||||
{
|
||||
public class StartupWithEndpointRouting
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie(options => options.LoginPath = "/Login");
|
||||
|
||||
services.AddMvc()
|
||||
.AddRazorPagesOptions(options =>
|
||||
{
|
||||
options.Conventions.AuthorizeFolder("/Admin");
|
||||
})
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseRouting(routes =>
|
||||
{
|
||||
routes.MapApplication();
|
||||
});
|
||||
|
||||
app.UseAuthorization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Authentication;
|
|||
using Microsoft.AspNetCore.Authorization.Policy;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Endpoints;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authorization
|
||||
|
|
@ -45,11 +44,19 @@ namespace Microsoft.AspNetCore.Authorization
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var endpoint = context.GetEndpoint();
|
||||
|
||||
// Workaround for https://github.com/aspnet/AspNetCore/issues/7011. Do not use the AuthorizationMiddleware for Razor Pages
|
||||
if (endpoint.Metadata.Any(m => m.GetType().FullName == "Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteMetadata"))
|
||||
{
|
||||
await _next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Flag to indicate to other systems, e.g. MVC, that authorization middleware was run for this request
|
||||
context.Items[AuthorizationMiddlewareInvokedKey] = AuthorizationMiddlewareInvokedValue;
|
||||
|
||||
// IMPORTANT: Changes to authorization logic should be mirrored in MVC's AuthorizeFilter
|
||||
var endpoint = context.GetEndpoint();
|
||||
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
|
||||
var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
|
||||
if (policy == null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue