Fixes: U4-2577 Can't save umbraco user - without re-filling in the password

Fixes: U4-541 Wrong dictionary key when using in backend template names
This changes the way that the value that is stored in the auth cookie. Previously we just stored a GUID which was the user's contextid stored in the db, now we store encrypted values of a few necessary user objects. In 6.2 we'll actually set a real .Net user object on the HttpContext. For now, the http module will simply just ensure that the culture is set correctly for the currently logged in user.
This commit is contained in:
Shannon
2013-08-02 15:16:04 +10:00
parent 3435a75e9e
commit c4b44ea0e3
14 changed files with 564 additions and 123 deletions

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Caching;
using System.Web.Security;
using System.Xml;
using System.Configuration;
@@ -299,6 +300,32 @@ namespace Umbraco.Core.Configuration
}
}
internal static string AuthCookieName
{
get
{
var value = GetKey("/settings/security/authCookieName");
if (string.IsNullOrEmpty(value) == false)
{
return value;
}
return "UMB_UCONTEXT";
}
}
internal static string AuthCookieDomain
{
get
{
var value = GetKey("/settings/security/authCookieDomain");
if (string.IsNullOrEmpty(value) == false)
{
return value;
}
return FormsAuthentication.CookieDomain;
}
}
/// <summary>
/// Enables the experimental canvas (live) editing on the frontend of the website
/// </summary>

View File

@@ -0,0 +1,199 @@
using System;
using System.Web;
using System.Web.Security;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Security
{
internal static class FormsAuthenticationTicketExtensions
{
public static UmbracoBackOfficeIdentity CreateUmbracoIdentity(this FormsAuthenticationTicket ticket)
{
try
{
//create the Umbraco user identity
return new UmbracoBackOfficeIdentity(ticket);
}
catch (Exception ex)
{
//This might occur if we cannot decrypt the value in which case we'll just ignore it, it will
// be handled by the base pages
LogHelper.Error(typeof(FormsAuthenticationTicketExtensions), "An error occurred decrypting the user's ticket", ex);
return null;
}
}
}
/// <summary>
/// Extensions to create and renew and remove authentication tickets for the Umbraco back office
/// </summary>
internal static class AuthenticationExtensions
{
//public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http)
//{
// return http.User.Identity as UmbracoBackOfficeIdentity;
//}
//internal static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContext http)
//{
// return new HttpContextWrapper(http).GetCurrentIdentity();
//}
/// <summary>
/// This clears the authentication cookie
/// </summary>
public static void UmbracoLogout(this HttpContextBase http)
{
Logout(http, UmbracoSettings.AuthCookieName);
}
internal static void UmbracoLogout(this HttpContext http)
{
new HttpContextWrapper(http).UmbracoLogout();
}
/// <summary>
/// Creates the umbraco authentication ticket
/// </summary>
/// <param name="http"></param>
/// <param name="userdata"></param>
public static void CreateUmbracoAuthTicket(this HttpContextBase http, UserData userdata)
{
CreateAuthTicket(
http,
userdata,
//This is one full day... this is how Umbraco has always created this cookie, it is setup to always
//expire one day from issue and it never gets updated.
1440,
"/",
UmbracoSettings.AuthCookieName,
UmbracoSettings.AuthCookieDomain);
}
internal static void CreateUmbracoAuthTicket(this HttpContext http, UserData userdata)
{
new HttpContextWrapper(http).CreateUmbracoAuthTicket(userdata);
}
/// <summary>
/// Gets the umbraco auth ticket
/// </summary>
/// <param name="http"></param>
/// <returns></returns>
public static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContextBase http)
{
return GetAuthTicket(http, UmbracoSettings.AuthCookieName);
}
internal static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContext http)
{
return new HttpContextWrapper(http).GetUmbracoAuthTicket();
}
/// <summary>
/// This clears the authentication cookie
/// </summary>
/// <param name="http"></param>
/// <param name="cookieName"></param>
private static void Logout(this HttpContextBase http, string cookieName)
{
//remove from the request
http.Request.Cookies.Remove(cookieName);
//expire from the response
var formsCookie = http.Response.Cookies[cookieName];
if (formsCookie != null)
{
//this will expire immediately and be removed from the browser
formsCookie.Expires = DateTime.Now.AddYears(-1);
}
else
{
//ensure there's def an expired cookie
http.Response.Cookies.Add(new HttpCookie(cookieName) { Expires = DateTime.Now.AddYears(-1) });
}
}
/// <summary>
/// In v6 this is a custom cookie, in v7 this is a real formsauth cookie.
/// </summary>
/// <param name="http"></param>
/// <param name="cookieName"></param>
/// <returns></returns>
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
{
var formsCookie = http.Request.Cookies[cookieName];
if (formsCookie == null)
{
return null;
}
try
{
//get the cookie value
var cookieVal = formsCookie.Value.DecryptWithMachineKey();
//here we need to see if the cookie val can be serialized into UserData, if not it means it's probably an old cookie
var deserialized = JsonConvert.DeserializeObject<UserData>(cookieVal);
//in v6, we're not using real FormsAuth but our own custom cookie and then we just return a custom FormsAuth ticket
// for this request.
return new FormsAuthenticationTicket(
4,
deserialized.RealName,
DateTime.Now,
DateTime.Now.AddMinutes(GlobalSettings.TimeOutInMinutes),
false,
cookieVal,
"/");
}
catch (Exception)
{
//occurs when decryption fails
http.Logout(cookieName);
return null;
}
}
/// <summary>
/// Creates a custom umbraco auth cookie with the data specified
/// </summary>
/// <param name="http">The HTTP.</param>
/// <param name="userData">The user data.</param>
/// <param name="minutesPersisted">The minutes persisted.</param>
/// <param name="cookiePath">The cookie path.</param>
/// <param name="cookieName">Name of the cookie.</param>
/// <param name="cookieDomain">The cookie domain.</param>
private static void CreateAuthTicket(this HttpContextBase http,
UserData userData,
int minutesPersisted,
string cookiePath,
string cookieName,
string cookieDomain)
{
var cookie = new HttpCookie(cookieName);
if (GlobalSettings.UseSSL)
cookie.Secure = true;
//ensure http only, this should only be able to be accessed via the server
cookie.HttpOnly = true;
cookie.Path = cookiePath;
cookie.Domain = cookieDomain;
cookie.Expires = DateTime.Now.AddMinutes(minutesPersisted);
//serialize the user data
var json = JsonConvert.SerializeObject(userData);
//encrypt it
var encTicket = json.EncryptWithMachineKey();
//set the cookie value
cookie.Value = encTicket;
http.Response.Cookies.Set(cookie);
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Web;
using System.Web.Security;
using Newtonsoft.Json;
namespace Umbraco.Core.Security
{
/// <summary>
/// A custom user identity for the Umbraco backoffice
/// </summary>
/// <remarks>
/// All values are lazy loaded for performance reasons as the constructor is called for every single request
/// </remarks>
internal class UmbracoBackOfficeIdentity : FormsIdentity
{
public UmbracoBackOfficeIdentity(FormsAuthenticationTicket ticket)
: base(ticket)
{
UserData = ticket.UserData;
EnsureDeserialized();
}
protected readonly string UserData;
internal UserData DeserializedData;
public string UserContextId
{
get { return DeserializedData.UserContextId; }
}
public int StartContentNode
{
get { return DeserializedData.StartContentNode; }
}
public int StartMediaNode
{
get { return DeserializedData.StartMediaNode; }
}
public string[] AllowedApplications
{
get { return DeserializedData.AllowedApplications; }
}
public object Id
{
get { return DeserializedData.Id; }
}
public string RealName
{
get { return DeserializedData.RealName; }
}
public string Culture
{
get { return DeserializedData.Culture; }
}
//public int SessionTimeout
//{
// get
// {
// EnsureDeserialized();
// return DeserializedData.SessionTimeout;
// }
//}
public string[] Roles
{
get { return DeserializedData.Roles; }
}
/// <summary>
/// This will ensure we only deserialize once
/// </summary>
/// <remarks>
/// For performance reasons, we'll also check if there's an http context available,
/// if so, we'll chuck our instance in there so that we only deserialize once per request.
/// </remarks>
protected void EnsureDeserialized()
{
if (DeserializedData != null)
return;
if (HttpContext.Current != null)
{
//check if we've already done this in this request
var data = HttpContext.Current.Items[typeof(UmbracoBackOfficeIdentity)] as UserData;
if (data != null)
{
DeserializedData = data;
return;
}
}
if (string.IsNullOrEmpty(UserData))
{
throw new NullReferenceException("The " + typeof(UserData) + " found in the ticket cannot be empty");
}
DeserializedData = JsonConvert.DeserializeObject<UserData>(UserData);
if (HttpContext.Current != null)
{
HttpContext.Current.Items[typeof (UmbracoBackOfficeIdentity)] = DeserializedData;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.Core.Security
{
/// <summary>
/// Data structure used to store information in the authentication cookie
/// </summary>
[DataContract(Name = "userData", Namespace = "")]
internal class UserData
{
public UserData()
{
AllowedApplications = new string[] {};
Roles = new string[] {};
}
///// <summary>
///// When their session is going to expire (in ticks)
///// </summary>
//[DataMember(Name = "timeout")]
//public long Timeout { get; set; }
[DataMember(Name = "userContextId")]
public string UserContextId { get; set; }
[DataMember(Name = "id")]
public object Id { get; set; }
[DataMember(Name = "roles")]
public string[] Roles { get; set; }
[DataMember(Name = "username")]
public string Username { get; set; }
[DataMember(Name = "name")]
public string RealName { get; set; }
[DataMember(Name = "startContent")]
public int StartContentNode { get; set; }
[DataMember(Name = "startMedia")]
public int StartMediaNode { get; set; }
[DataMember(Name = "allowedApps")]
public string[] AllowedApplications { get; set; }
[DataMember(Name = "culture")]
public string Culture { get; set; }
}
}

View File

@@ -666,6 +666,9 @@
<Compile Include="Publishing\PublishStatus.cs" />
<Compile Include="Publishing\PublishStatusType.cs" />
<Compile Include="RenderingEngine.cs" />
<Compile Include="Security\AuthenticationExtensions.cs" />
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
<Compile Include="Security\UserData.cs" />
<Compile Include="Serialization\AbstractSerializationService.cs" />
<Compile Include="Serialization\Formatter.cs" />
<Compile Include="Serialization\IFormatter.cs" />

View File

@@ -12,6 +12,7 @@ namespace Umbraco.Core
/// </summary>
public static class UriExtensions
{
/// <summary>
/// Checks if the current uri is a back office request
/// </summary>
@@ -19,11 +20,14 @@ namespace Umbraco.Core
/// <returns></returns>
internal static bool IsBackOfficeRequest(this Uri url)
{
var authority = url.GetLeftPart(UriPartial.Authority);
var afterAuthority = url.GetLeftPart(UriPartial.Query)
.TrimStart(authority)
.TrimStart("/");
//check if this is in the umbraco back office
return afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/"));
}

View File

@@ -5,7 +5,7 @@
<user>0</user>
<startNode>1080</startNode>
<fullTree>False</fullTree>
<documentTypeAlias>Home</documentTypeAlias>
<documentTypeAlias>Base</documentTypeAlias>
<fields>
<categories>
</categories>
@@ -14,6 +14,6 @@
<excerpt>
</excerpt>
</fields>
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="image" mediaTypeFileProperty="umbracoFile" />
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="Image" mediaTypeFileProperty="umbracoFile" />
</channel>
</metablogapi>

View File

@@ -1,16 +1,34 @@
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="passwordChanger.ascx.cs" Inherits="umbraco.controls.passwordChanger" %>
<a href="#" onclick="if (document.getElementById('umbPasswordChanger').style.display == '' || document.getElementById('umbPasswordChanger').style.display == 'none') {document.getElementById('umbPasswordChanger').style.display = 'block'; this.style.display = 'none';}">Change password</a><br />
<script type="text/javascript">
(function ($) {
Umbraco.Sys.registerNamespace("Umbraco.Controls");
Umbraco.Controls.PasswordChanger = {
toggle: function (e) {
if (!$("#umbPasswordChanger").is(":visible")) {
ValidatorEnable(document.getElementById('<%=CompareValidator1.ClientID %>'), true);
$(e).closest(".propertyItem").replaceWith($("#umbPasswordChanger"));
$("#umbPasswordChanger").show();
$(e).hide();
}
}
};
})(jQuery);
</script>
<div id="umbPasswordChanger" style="display: none;">
<table>
<tr><th style="width: 270px;"><%=umbraco.ui.GetText("user", "newPassword")%>:</th><td style="width: 359px">
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
</td></tr>
<tr><th><%=umbraco.ui.GetText("user", "confirmNewPassword")%>:</th><td style="width: 359px">
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
</td></tr>
</table>
</div>
<a href="#" onclick="Umbraco.Controls.PasswordChanger.toggle(this);">Change password</a><br />
<div class="propertyItem" id="umbPasswordChanger" style="display: none;">
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "newPassword")%></div>
<div class="propertyItemContent">
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
</div>
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "confirmNewPassword")%></div>
<div class="propertyItemContent">
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server" Enabled="False" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
</div>
</div>

View File

@@ -5,12 +5,15 @@ using System.Web;
using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Security;
using umbraco;
using umbraco.BusinessLogic;
using umbraco.DataLayer;
using umbraco.businesslogic.Exceptions;
using umbraco.cms.businesslogic.member;
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings;
namespace Umbraco.Web.Security
{
@@ -369,53 +372,51 @@ namespace Umbraco.Web.Security
/// </summary>
/// <value>The umbraco user context ID.</value>
public string UmbracoUserContextId
{
{
get
{
if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue)
var authTicket = HttpContext.Current.GetUmbracoAuthTicket();
if (authTicket == null)
{
try
{
var encTicket = StateHelper.Cookies.UserContext.GetValue();
if (string.IsNullOrEmpty(encTicket) == false)
{
return encTicket.DecryptWithMachineKey();
}
}
catch (Exception ex)
{
if (ex is ArgumentException || ex is FormatException || ex is HttpException)
{
StateHelper.Cookies.UserContext.Clear();
}
else
{
throw;
}
}
return "";
}
return "";
var identity = authTicket.CreateUmbracoIdentity();
if (identity == null)
{
HttpContext.Current.UmbracoLogout();
return "";
}
return identity.UserContextId;
}
set
{
// zb-00004 #29956 : refactor cookies names & handling
if (StateHelper.Cookies.HasCookies)
if (value.IsNullOrWhiteSpace())
{
// Clearing all old cookies before setting a new one.
if (StateHelper.Cookies.UserContext.HasValue)
StateHelper.Cookies.ClearAll();
if (string.IsNullOrEmpty(value) == false)
HttpContext.Current.UmbracoLogout();
}
else
{
var uid = GetUserId(value);
if (uid == -1)
{
// Encrypt the value
var encTicket = value.EncryptWithMachineKey();
// Create new cookie.
StateHelper.Cookies.UserContext.SetValue(encTicket, 1);
HttpContext.Current.UmbracoLogout();
}
else
{
StateHelper.Cookies.UserContext.Clear();
var user = User.GetUser(uid);
HttpContext.Current.CreateUmbracoAuthTicket(
new UserData
{
Id = uid,
AllowedApplications = user.Applications.Select(x => x.alias).ToArray(),
Culture = ui.Culture(user),
RealName = user.Name,
Roles = new string[] { user.UserType.Alias },
StartContentNode = user.StartNodeId,
StartMediaNode = user.StartMediaId,
UserContextId = value,
Username = user.LoginName
});
}
}
}

View File

@@ -51,14 +51,6 @@ namespace Umbraco.Web.UI.Pages
Response.Redirect(SystemDirectories.Umbraco + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl), true);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(Security.CurrentUser));
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
/// <summary>
/// Gets/sets the app that this page is assigned to

View File

@@ -2,13 +2,17 @@
using System.Collections;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Routing;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Security;
using Umbraco.Web.Routing;
using umbraco;
using umbraco.BasePages;
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Web.Configuration;
@@ -29,7 +33,7 @@ namespace Umbraco.Web
/// Begins to process a request.
/// </summary>
/// <param name="httpContext"></param>
void BeginRequest(HttpContextBase httpContext)
static void BeginRequest(HttpContextBase httpContext)
{
//we need to set the initial url in our ApplicationContext, this is so our keep alive service works and this must
//exist on a global context because the keep alive service doesn't run in a web context.
@@ -119,6 +123,58 @@ namespace Umbraco.Web
RewriteToUmbracoHandler(httpContext, pcr);
}
/// <summary>
/// Checks if the request is authenticated, if it is it sets the thread culture to the currently logged in user
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void AuthenticateRequest(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
var http = new HttpContextWrapper(app.Context);
// do not process if client-side request
if (http.Request.Url.IsClientSideRequest())
return;
if (app.Request.Url.IsBackOfficeRequest() || app.Request.Url.IsInstallerRequest())
{
var ticket = http.GetUmbracoAuthTicket();
if (ticket != null)
{
//create the Umbraco user identity
var identity = ticket.CreateUmbracoIdentity();
if (identity != null)
{
//We'll leave setting custom identies/principals for 6.2, for now we'll just ensure that the cultures, etc.. are set
////set the principal object
////now we need to see if their session is still valid
//var timeout = BasePage.GetTimeout(identity.UserContextId);
//if (timeout > DateTime.Now.Ticks)
//{
//var principal = new GenericPrincipal(identity, identity.Roles);
////It is actually not good enough to set this on the current app Context and the thread, it also needs
//// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
//// an underlying fault of asp.net not propogating the User correctly.
//if (HttpContext.Current != null)
//{
// HttpContext.Current.User = principal;
//}
//app.Context.User = principal;
//Thread.CurrentPrincipal = principal;
//}
//This is a back office/installer request, we will also set the culture/ui culture
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture =
new System.Globalization.CultureInfo(identity.Culture);
}
}
}
}
// returns a value indicating whether redirection took place and the request has
// been completed - because we don't want to Response.End() here to terminate
// everything properly.
@@ -433,6 +489,8 @@ namespace Umbraco.Web
BeginRequest(new HttpContextWrapper(httpContext));
};
app.AuthenticateRequest += AuthenticateRequest;
app.PostResolveRequestCache += (sender, e) =>
{
var httpContext = ((HttpApplication)sender).Context;

View File

@@ -348,16 +348,12 @@ namespace umbraco.cms.presentation.user
}
}
}
#region Web Form Designer generated code
protected override void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
//lapps.SelectionMode = ListSelectionMode.Multiple;
lapps.RepeatLayout = RepeatLayout.Flow;
lapps.RepeatDirection = RepeatDirection.Vertical;
}
protected override void OnPreRender(EventArgs e)
@@ -366,23 +362,9 @@ namespace umbraco.cms.presentation.user
ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/CMSNode.asmx"));
// ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx"));
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//lapps.SelectionMode = ListSelectionMode.Multiple;
lapps.RepeatLayout = RepeatLayout.Flow;
lapps.RepeatDirection = RepeatDirection.Vertical;
}
#endregion
/// <summary>
/// Handles the Click event of the saveUser control.
/// </summary>

View File

@@ -14,6 +14,7 @@ using Umbraco.Core.Services;
using umbraco.BusinessLogic;
using umbraco.DataLayer;
using Umbraco.Core;
using Umbraco.Core.Security;
namespace umbraco.BasePages
{
@@ -223,10 +224,10 @@ namespace umbraco.BasePages
return false;
}
private static long GetTimeout(string umbracoUserContextID)
internal static long GetTimeout(string umbracoUserContextId)
{
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
CacheKeys.UserContextTimeoutCacheKey + umbracoUserContextID,
CacheKeys.UserContextTimeoutCacheKey + umbracoUserContextId,
new TimeSpan(0, UmbracoTimeOutInMinutes / 10, 0),
() => GetTimeout(true));
}
@@ -257,50 +258,48 @@ namespace umbraco.BasePages
{
get
{
if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue)
var authTicket = HttpContext.Current.GetUmbracoAuthTicket();
if (authTicket == null)
{
try
{
var encTicket = StateHelper.Cookies.UserContext.GetValue();
if (string.IsNullOrEmpty(encTicket) == false)
{
return encTicket.DecryptWithMachineKey();
}
}
catch (Exception ex)
{
if (ex is ArgumentException || ex is FormatException || ex is HttpException)
{
StateHelper.Cookies.UserContext.Clear();
}
else
{
throw;
}
}
return "";
}
return "";
var identity = authTicket.CreateUmbracoIdentity();
if (identity == null)
{
HttpContext.Current.UmbracoLogout();
return "";
}
return identity.UserContextId;
}
set
{
// zb-00004 #29956 : refactor cookies names & handling
if (StateHelper.Cookies.HasCookies)
if (value.IsNullOrWhiteSpace())
{
// Clearing all old cookies before setting a new one.
if (StateHelper.Cookies.UserContext.HasValue)
StateHelper.Cookies.ClearAll();
if (string.IsNullOrEmpty(value) == false)
{
// Encrypt the value
var encTicket = value.EncryptWithMachineKey();
// Create new cookie.
StateHelper.Cookies.UserContext.SetValue(encTicket, 1);
HttpContext.Current.UmbracoLogout();
}
else
{
var uid = GetUserId(value);
if (uid == -1)
{
HttpContext.Current.UmbracoLogout();
}
else
{
StateHelper.Cookies.UserContext.Clear();
var user = BusinessLogic.User.GetUser(uid);
HttpContext.Current.CreateUmbracoAuthTicket(
new UserData
{
Id = uid,
AllowedApplications = user.Applications.Select(x => x.alias).ToArray(),
Culture = ui.Culture(user),
RealName = user.Name,
Roles = new string[] {user.UserType.Alias},
StartContentNode = user.StartNodeId,
StartMediaNode = user.StartMediaId,
UserContextId = value,
Username = user.LoginName
});
}
}
}

View File

@@ -108,9 +108,6 @@ namespace umbraco.BasePages
else
Response.Redirect(SystemDirectories.Umbraco + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl), true);
}
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(this.getUser()));
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
}
}