Merge pull request #9916 from umbraco/netcore/bugfix/AB10710_UmbracoContext_should_not_use_IBackOfficeSecurity

Netcore: Fix coupling between IBackOfficeSecurity and IUmbracoContext
This commit is contained in:
Shannon Deminick
2021-03-09 12:49:53 +11:00
committed by GitHub
4 changed files with 39 additions and 33 deletions

View File

@@ -8,7 +8,6 @@ using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Tests.Common;
using Umbraco.Cms.Web.Common.AspNetCore;
@@ -57,9 +56,6 @@ namespace Umbraco.Cms.Tests.UnitTests.TestHelpers.Objects
IHostingEnvironment hostingEnvironment = TestHelper.GetHostingEnvironment();
var backofficeSecurityAccessorMock = new Mock<IBackOfficeSecurityAccessor>();
backofficeSecurityAccessorMock.Setup(x => x.BackOfficeSecurity).Returns(Mock.Of<IBackOfficeSecurity>());
var umbracoContextFactory = new UmbracoContextFactory(
umbracoContextAccessor,
snapshotService.Object,
@@ -69,8 +65,7 @@ namespace Umbraco.Cms.Tests.UnitTests.TestHelpers.Objects
hostingEnvironment,
new UriUtility(hostingEnvironment),
new AspNetCoreCookieManager(httpContextAccessor),
Mock.Of<IRequestAccessor>(),
backofficeSecurityAccessorMock.Object);
httpContextAccessor);
return umbracoContextFactory;
}

View File

@@ -1,13 +1,27 @@
using System;
using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Umbraco.Cms.Core.Security;
namespace Umbraco.Extensions
{
public static class HttpContextExtensions
{
/// <summary>
/// Get the value in the request form or query string for the key
/// </summary>
public static string GetRequestValue(this HttpContext context, string key)
{
HttpRequest request = context.Request;
if (!request.HasFormContentType)
{
return request.Query[key];
}
string value = request.Form[key];
return value ?? request.Query[key];
}
public static void SetPrincipalForRequest(this HttpContext context, ClaimsPrincipal principal)
{
context.User = principal;

View File

@@ -1,10 +1,11 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
@@ -18,12 +19,12 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
private readonly IHostingEnvironment _hostingEnvironment;
private readonly UriUtility _uriUtility;
private readonly ICookieManager _cookieManager;
private readonly IRequestAccessor _requestAccessor;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly Lazy<IPublishedSnapshot> _publishedSnapshot;
private string _previewToken;
private bool? _previewing;
private readonly IBackOfficeSecurity _backofficeSecurity;
private readonly UmbracoRequestPaths _umbracoRequestPaths;
private Uri _requestUrl;
private Uri _originalRequestUrl;
private Uri _cleanedUmbracoUrl;
@@ -33,13 +34,12 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
// warn: does *not* manage setting any IUmbracoContextAccessor
internal UmbracoContext(
IPublishedSnapshotService publishedSnapshotService,
IBackOfficeSecurity backofficeSecurity,
UmbracoRequestPaths umbracoRequestPaths,
IHostingEnvironment hostingEnvironment,
IVariationContextAccessor variationContextAccessor,
UriUtility uriUtility,
ICookieManager cookieManager,
IRequestAccessor requestAccessor)
IHttpContextAccessor httpContextAccessor)
{
if (publishedSnapshotService == null)
{
@@ -50,11 +50,9 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
_uriUtility = uriUtility;
_hostingEnvironment = hostingEnvironment;
_cookieManager = cookieManager;
_requestAccessor = requestAccessor;
_httpContextAccessor = httpContextAccessor;
ObjectCreated = DateTime.Now;
UmbracoRequestId = Guid.NewGuid();
_backofficeSecurity = backofficeSecurity ?? throw new ArgumentNullException(nameof(backofficeSecurity));
_umbracoRequestPaths = umbracoRequestPaths;
// beware - we cannot expect a current user here, so detecting preview mode must be a lazy thing
@@ -72,6 +70,11 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
/// </remarks>
internal Guid UmbracoRequestId { get; }
// lazily get/create a Uri for the current request
private Uri RequestUrl => _requestUrl ??= _httpContextAccessor.HttpContext is null
? null
: new Uri(_httpContextAccessor.HttpContext.Request.GetEncodedUrl());
/// <inheritdoc/>
// set the urls lazily, no need to allocate until they are needed...
// NOTE: The request will not be available during app startup so we can only set this to an absolute URL of localhost, this
@@ -79,7 +82,7 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
// 'could' still generate URLs during startup BUT any domain driven URL generation will not work because it is NOT possible to get
// the current domain during application startup.
// see: http://issues.umbraco.org/issue/U4-1890
public Uri OriginalRequestUrl => _originalRequestUrl ?? (_originalRequestUrl = _requestAccessor.GetRequestUrl() ?? new Uri("http://localhost"));
public Uri OriginalRequestUrl => _originalRequestUrl ?? (_originalRequestUrl = RequestUrl ?? new Uri("http://localhost"));
/// <inheritdoc/>
// set the urls lazily, no need to allocate until they are needed...
@@ -106,8 +109,8 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
/// <inheritdoc/>
public bool IsDebug => // NOTE: the request can be null during app startup!
_hostingEnvironment.IsDebugMode
&& (string.IsNullOrEmpty(_requestAccessor.GetRequestValue("umbdebugshowtrace")) == false
|| string.IsNullOrEmpty(_requestAccessor.GetRequestValue("umbdebug")) == false
&& (string.IsNullOrEmpty(_httpContextAccessor.HttpContext.GetRequestValue("umbdebugshowtrace")) == false
|| string.IsNullOrEmpty(_httpContextAccessor.HttpContext.GetRequestValue("umbdebug")) == false
|| string.IsNullOrEmpty(_cookieManager.GetCookieValue("UMB-DEBUG")) == false);
/// <inheritdoc/>
@@ -140,10 +143,9 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
private void DetectPreviewMode()
{
Uri requestUrl = _requestAccessor.GetRequestUrl();
if (requestUrl != null
&& _umbracoRequestPaths.IsBackOfficeRequest(requestUrl.AbsolutePath) == false
&& _backofficeSecurity.CurrentUser != null)
if (RequestUrl != null
&& _umbracoRequestPaths.IsBackOfficeRequest(RequestUrl.AbsolutePath) == false
&& _httpContextAccessor.HttpContext?.GetCurrentIdentity() != null)
{
var previewToken = _cookieManager.GetCookieValue(Core.Constants.Web.PreviewCookieName); // may be null or empty
_previewToken = previewToken.IsNullOrWhiteSpace() ? null : previewToken;

View File

@@ -1,10 +1,10 @@
using System;
using Microsoft.AspNetCore.Http;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Web;
namespace Umbraco.Cms.Web.Common.UmbracoContext
@@ -18,12 +18,10 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
private readonly UmbracoRequestPaths _umbracoRequestPaths;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly ICookieManager _cookieManager;
private readonly IRequestAccessor _requestAccessor;
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly UriUtility _uriUtility;
/// <summary>
@@ -38,8 +36,7 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
IHostingEnvironment hostingEnvironment,
UriUtility uriUtility,
ICookieManager cookieManager,
IRequestAccessor requestAccessor,
IBackOfficeSecurityAccessor backofficeSecurityAccessor)
IHttpContextAccessor httpContextAccessor)
{
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
_publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService));
@@ -49,8 +46,7 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
_uriUtility = uriUtility ?? throw new ArgumentNullException(nameof(uriUtility));
_cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager));
_requestAccessor = requestAccessor ?? throw new ArgumentNullException(nameof(requestAccessor));
_backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor));
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
private IUmbracoContext CreateUmbracoContext()
@@ -75,13 +71,12 @@ namespace Umbraco.Cms.Web.Common.UmbracoContext
return new UmbracoContext(
_publishedSnapshotService,
_backofficeSecurityAccessor.BackOfficeSecurity,
_umbracoRequestPaths,
_hostingEnvironment,
_variationContextAccessor,
_uriUtility,
_cookieManager,
_requestAccessor);
_httpContextAccessor);
}
/// <inheritdoc />