Merge branch 'v9/dev' into v9/task/more-flexible-startup
# Conflicts: # src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs
This commit is contained in:
@@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Infrastructure.DependencyInjection;
|
||||
using Umbraco.Cms.Web.Common.Middleware;
|
||||
using Umbraco.Cms.Web.Common.Routing;
|
||||
using Umbraco.Cms.Web.Website.Collections;
|
||||
using Umbraco.Cms.Web.Website.Controllers;
|
||||
@@ -47,6 +48,7 @@ namespace Umbraco.Extensions
|
||||
builder.Services.AddSingleton<MemberModelBuilderFactory>();
|
||||
|
||||
builder.Services.AddSingleton<PublicAccessMiddleware>();
|
||||
builder.Services.AddSingleton<BasicAuthenticationMiddleware>();
|
||||
|
||||
builder
|
||||
.AddDistributedCache()
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Web.Common.ApplicationBuilder;
|
||||
using Umbraco.Cms.Web.Common.Middleware;
|
||||
using Umbraco.Cms.Web.Website.Middleware;
|
||||
using Umbraco.Cms.Web.Website.Routing;
|
||||
|
||||
@@ -20,6 +21,7 @@ namespace Umbraco.Extensions
|
||||
public static IUmbracoApplicationBuilderContext UseWebsite(this IUmbracoApplicationBuilderContext builder)
|
||||
{
|
||||
builder.AppBuilder.UseMiddleware<PublicAccessMiddleware>();
|
||||
builder.AppBuilder.UseMiddleware<BasicAuthenticationMiddleware>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the content last chance finder.</typeparam>
|
||||
/// <param name="builder">The builder.</param>
|
||||
public static void SetContentLastChanceFinder<T>(this IUmbracoBuilder builder)
|
||||
public static IUmbracoBuilder SetContentLastChanceFinder<T>(this IUmbracoBuilder builder)
|
||||
where T : class, IContentLastChanceFinder
|
||||
{
|
||||
builder.Services.AddUnique<IContentLastChanceFinder, T>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -27,9 +28,10 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <param name="factory">A function creating a last chance finder.</param>
|
||||
public static void SetContentLastChanceFinder(this IUmbracoBuilder builder, Func<IServiceProvider, IContentLastChanceFinder> factory)
|
||||
public static IUmbracoBuilder SetContentLastChanceFinder(this IUmbracoBuilder builder, Func<IServiceProvider, IContentLastChanceFinder> factory)
|
||||
{
|
||||
builder.Services.AddUnique(factory);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,9 +39,10 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <param name="finder">A last chance finder.</param>
|
||||
public static void SetContentLastChanceFinder(this IUmbracoBuilder builder, IContentLastChanceFinder finder)
|
||||
public static IUmbracoBuilder SetContentLastChanceFinder(this IUmbracoBuilder builder, IContentLastChanceFinder finder)
|
||||
{
|
||||
builder.Services.AddUnique(finder);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,10 +50,11 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the site domain helper.</typeparam>
|
||||
/// <param name="builder"></param>
|
||||
public static void SetSiteDomainHelper<T>(this IUmbracoBuilder builder)
|
||||
public static IUmbracoBuilder SetSiteDomainHelper<T>(this IUmbracoBuilder builder)
|
||||
where T : class, ISiteDomainMapper
|
||||
{
|
||||
builder.Services.AddUnique<ISiteDomainMapper, T>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,9 +62,10 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <param name="factory">A function creating a helper.</param>
|
||||
public static void SetSiteDomainHelper(this IUmbracoBuilder builder, Func<IServiceProvider, ISiteDomainMapper> factory)
|
||||
public static IUmbracoBuilder SetSiteDomainHelper(this IUmbracoBuilder builder, Func<IServiceProvider, ISiteDomainMapper> factory)
|
||||
{
|
||||
builder.Services.AddUnique(factory);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,9 +73,10 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <param name="helper">A helper.</param>
|
||||
public static void SetSiteDomainHelper(this IUmbracoBuilder builder, ISiteDomainMapper helper)
|
||||
public static IUmbracoBuilder SetSiteDomainHelper(this IUmbracoBuilder builder, ISiteDomainMapper helper)
|
||||
{
|
||||
builder.Services.AddUnique(helper);
|
||||
return builder;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Web.BackOffice.Security;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides basic authentication via back-office credentials for public website access if configured for use and the client IP is not allow listed.
|
||||
/// </summary>
|
||||
public class BasicAuthenticationMiddleware : IMiddleware
|
||||
{
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
private readonly IBasicAuthService _basicAuthService;
|
||||
|
||||
public BasicAuthenticationMiddleware(
|
||||
IRuntimeState runtimeState,
|
||||
IBasicAuthService basicAuthService)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_basicAuthService = basicAuthService;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
if (_runtimeState.Level < RuntimeLevel.Run || context.Request.IsBackOfficeRequest() || !_basicAuthService.IsBasicAuthEnabled())
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
IPAddress clientIPAddress = context.Connection.RemoteIpAddress;
|
||||
if (_basicAuthService.IsIpAllowListed(clientIPAddress))
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
AuthenticateResult authenticateResult = await context.AuthenticateBackOfficeAsync();
|
||||
if (authenticateResult.Succeeded)
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.TryGetBasicAuthCredentials(out var username, out var password))
|
||||
{
|
||||
IBackOfficeSignInManager backOfficeSignInManager =
|
||||
context.RequestServices.GetService<IBackOfficeSignInManager>();
|
||||
|
||||
if (backOfficeSignInManager is not null)
|
||||
{
|
||||
SignInResult signInResult =
|
||||
await backOfficeSignInManager.PasswordSignInAsync(username, password, false, true);
|
||||
|
||||
if (signInResult.Succeeded)
|
||||
{
|
||||
await next.Invoke(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUnauthorizedHeader(context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUnauthorizedHeader(context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no authorization header
|
||||
SetUnauthorizedHeader(context);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetUnauthorizedHeader(HttpContext context)
|
||||
{
|
||||
context.Response.StatusCode = 401;
|
||||
context.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Umbraco login\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user