Fixes #11189 - protected content not working (#11193)

* Fixes #11189

* Fixes #11183

* Fix test Null_When_No_Content_On_PublishedRequest.

Believe this is reasonable.

* Update src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs

Co-authored-by: Paul Johnson <pmj@umbraco.com>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Shannon Deminick
2021-09-26 20:42:27 +10:00
committed by GitHub
parent cf52b4648d
commit 5bfab13dc5
4 changed files with 46 additions and 13 deletions

View File

@@ -163,7 +163,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Routing
public async Task Null_When_No_Content_On_PublishedRequest()
{
IUmbracoContext umbracoContext = GetUmbracoContext(true);
IPublishedRequest request = Mock.Of<IPublishedRequest>();
IPublishedRequest request = Mock.Of<IPublishedRequest>(x => x.PublishedContent == null);
UmbracoRouteValueTransformer transformer = GetTransformerWithRunState(
Mock.Of<IUmbracoContextAccessor>(x => x.TryGetUmbracoContext(out umbracoContext)),
@@ -172,9 +172,10 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Website.Routing
var httpContext = new DefaultHttpContext();
RouteValueDictionary result = await transformer.TransformAsync(httpContext, new RouteValueDictionary());
Assert.IsNull(result);
UmbracoRouteValues routeVals = httpContext.Features.Get<UmbracoRouteValues>();
Assert.IsNull(routeVals);
Assert.AreEqual(routeVals.PublishedRequest.GetRouteResult(), UmbracoRouteResult.NotFound);
}
[Test]

View File

@@ -1,8 +1,10 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.Common.Security
{
@@ -34,6 +36,19 @@ namespace Umbraco.Cms.Web.Common.Security
options.LogoutPath = null;
options.CookieManager = new MemberCookieManager(_runtimeState, _umbracoRequestPaths);
options.Events = new CookieAuthenticationEvents
{
OnSignedIn = ctx =>
{
// occurs when sign in is successful and after the ticket is written to the outbound cookie
// When we are signed in with the cookie, assign the principal to the current HttpContext
ctx.HttpContext.SetPrincipalForRequest(ctx.Principal);
return Task.CompletedTask;
}
};
}
}
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
@@ -65,6 +67,19 @@ namespace Umbraco.Cms.Web.Website.Routing
{
_logger.LogDebug("EnsurePublishedContentAccess: Page is protected, check for access");
// manually authenticate the request
AuthenticateResult authResult = await httpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
if (authResult.Succeeded)
{
// set the user to the auth result. we need to do this here because this occurs
// before the authentication middleware.
// NOTE: It would be possible to just pass the authResult to the HasMemberAccessToContentAsync method
// instead of relying directly on the user assigned to the http context, and then the auth middleware
// will run anyways and assign the user. Perhaps that is a little cleaner, but would require more code
// changes right now, and really it's not any different in the end result.
httpContext.SetPrincipalForRequest(authResult.Principal);
}
publicAccessStatus = await _publicAccessChecker.HasMemberAccessToContentAsync(publishedContent.Id);
switch (publicAccessStatus)
{

View File

@@ -130,17 +130,7 @@ namespace Umbraco.Cms.Web.Website.Routing
IPublishedRequest publishedRequest = await RouteRequestAsync(umbracoContext);
umbracoRouteValues = await _routeValuesFactory.CreateAsync(httpContext, publishedRequest);
if (!umbracoRouteValues?.PublishedRequest?.HasPublishedContent() ?? false)
{
// No content was found, not by any registered 404 handlers and
// not by the IContentLastChanceFinder. In this case we want to return
// our default 404 page but we cannot return route values now because
// it's possible that a developer is handling dynamic routes too.
// Our 404 page will be handled with the NotFoundSelectorPolicy
return null;
}
umbracoRouteValues = await _routeValuesFactory.CreateAsync(httpContext, publishedRequest);
// now we need to do some public access checks
umbracoRouteValues = await _publicAccessRequestHandler.RewriteForPublishedContentAccessAsync(httpContext, umbracoRouteValues);
@@ -155,6 +145,18 @@ namespace Umbraco.Cms.Web.Website.Routing
return HandlePostedValues(postedInfo, httpContext);
}
UmbracoRouteResult? routeResult = umbracoRouteValues?.PublishedRequest?.GetRouteResult();
if (!routeResult.HasValue || routeResult == UmbracoRouteResult.NotFound)
{
// No content was found, not by any registered 404 handlers and
// not by the IContentLastChanceFinder. In this case we want to return
// our default 404 page but we cannot return route values now because
// it's possible that a developer is handling dynamic routes too.
// Our 404 page will be handled with the NotFoundSelectorPolicy
return null;
}
// See https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.routing.dynamicroutevaluetransformer.transformasync?view=aspnetcore-5.0#Microsoft_AspNetCore_Mvc_Routing_DynamicRouteValueTransformer_TransformAsync_Microsoft_AspNetCore_Http_HttpContext_Microsoft_AspNetCore_Routing_RouteValueDictionary_
// We should apparenlty not be modified these values.
// So we create new ones.