diff --git a/src/Umbraco.Core/Security/AuthenticationExtensions.cs b/src/Umbraco.Core/Security/AuthenticationExtensions.cs index 17bb32675b..5adf163bee 100644 --- a/src/Umbraco.Core/Security/AuthenticationExtensions.cs +++ b/src/Umbraco.Core/Security/AuthenticationExtensions.cs @@ -1,8 +1,10 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using System.Globalization; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; @@ -441,5 +443,24 @@ namespace Umbraco.Core.Security return ticket; } + + /// + /// Ensures that the thread culture is set based on the back office user's culture + /// + /// + internal static void EnsureCulture(this IIdentity identity) + { + if (identity is UmbracoBackOfficeIdentity umbIdentity && umbIdentity.IsAuthenticated) + { + Thread.CurrentThread.CurrentUICulture = + Thread.CurrentThread.CurrentCulture = + UserCultures.GetOrAdd(umbIdentity.Culture, s => new CultureInfo(s)); + } + } + + /// + /// Used so that we aren't creating a new CultureInfo object for every single request + /// + private static readonly ConcurrentDictionary UserCultures = new ConcurrentDictionary(); } } diff --git a/src/Umbraco.Core/Security/BackOfficeCookieAuthenticationProvider.cs b/src/Umbraco.Core/Security/BackOfficeCookieAuthenticationProvider.cs index cb0ce2b147..b75dd76e47 100644 --- a/src/Umbraco.Core/Security/BackOfficeCookieAuthenticationProvider.cs +++ b/src/Umbraco.Core/Security/BackOfficeCookieAuthenticationProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Globalization; +using System.Runtime.CompilerServices; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; @@ -81,12 +82,13 @@ namespace Umbraco.Core.Security /// public override async Task ValidateIdentity(CookieValidateIdentityContext context) { - EnsureCulture(context); + //ensure the thread culture is set + context?.Identity?.EnsureCulture(); await EnsureValidSessionId(context); await base.ValidateIdentity(context); - } + } /// /// Ensures that the user has a valid session id @@ -100,20 +102,8 @@ namespace Umbraco.Core.Security await SessionIdValidator.ValidateSessionAsync(TimeSpan.FromMinutes(1), context); } - private void EnsureCulture(CookieValidateIdentityContext context) - { - var umbIdentity = context.Identity as UmbracoBackOfficeIdentity; - if (umbIdentity != null && umbIdentity.IsAuthenticated) - { - Thread.CurrentThread.CurrentCulture = - Thread.CurrentThread.CurrentUICulture = - UserCultures.GetOrAdd(umbIdentity.Culture, s => new CultureInfo(s)); - } - } + - /// - /// Used so that we aren't creating a new CultureInfo object for every single request - /// - private static readonly ConcurrentDictionary UserCultures = new ConcurrentDictionary(); + } } diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index b1709259c4..ec91509569 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -1,8 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; +using System.Threading; using System.Web; using System.Web.Routing; using LightInject; @@ -15,6 +17,7 @@ using Umbraco.Web.Security; using Umbraco.Core.Collections; using Umbraco.Core.Exceptions; using Umbraco.Core.Persistence; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; @@ -562,6 +565,13 @@ namespace Umbraco.Web } }; + app.PostAuthenticateRequest += (sender, e) => + { + var httpContext = ((HttpApplication) sender).Context; + //ensure the thread culture is set + httpContext.User?.Identity?.EnsureCulture(); + }; + app.PostResolveRequestCache += (sender, e) => { var httpContext = ((HttpApplication) sender).Context;