Updates password changing for users to use ASP.NET Identity, there's still some more work here to do to implement the IUserAwarePasswordHashing and to result some of the TODOs. Also moved all password changing logic to PasswordChanger even for legacy membership providers.

This commit is contained in:
Shannon
2017-07-20 12:53:09 +10:00
parent 5c75285543
commit 63befa55d5
13 changed files with 320 additions and 205 deletions

View File

@@ -137,7 +137,9 @@ namespace Umbraco.Core.Security
/// Initializes the user manager with the correct options
/// </summary>
/// <param name="manager"></param>
/// <param name="membershipProvider"></param>
/// <param name="membershipProvider">
/// The <see cref="MembershipProviderBase"/> for the users called UsersMembershipProvider
/// </param>
/// <param name="dataProtectionProvider"></param>
/// <returns></returns>
protected void InitUserManager(
@@ -153,11 +155,10 @@ namespace Umbraco.Core.Security
};
// Configure validation logic for passwords
var provider = MembershipProviderExtensions.GetUsersMembershipProvider();
manager.PasswordValidator = new MembershipProviderPasswordValidator(provider);
manager.PasswordValidator = new MembershipProviderPasswordValidator(membershipProvider);
//use a custom hasher based on our membership provider
manager.PasswordHasher = new MembershipPasswordHasher(membershipProvider);
manager.PasswordHasher = new MembershipProviderPasswordHasher(membershipProvider);
if (dataProtectionProvider != null)
{

View File

@@ -1,31 +0,0 @@
using Microsoft.AspNet.Identity;
namespace Umbraco.Core.Security
{
/// <summary>
/// A custom password hasher that conforms to the current password hashing done in Umbraco
/// </summary>
internal class MembershipPasswordHasher : IPasswordHasher
{
private readonly MembershipProviderBase _provider;
public MembershipPasswordHasher(MembershipProviderBase provider)
{
_provider = provider;
}
public string HashPassword(string password)
{
return _provider.HashPasswordForStorage(password);
}
public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
return _provider.VerifyPassword(providedPassword, hashedPassword)
? PasswordVerificationResult.Success
: PasswordVerificationResult.Failed;
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using Microsoft.AspNet.Identity;
namespace Umbraco.Core.Security
{
public interface IUserAwarePasswordHasher<TKey>
where TKey : IEquatable<TKey>
{
string HashPassword(TKey id, string password);
string VerifyHashedPassword(TKey id, string hashedPassword, string providedPassword);
}
public interface IMembershipProviderPasswordHasher : IPasswordHasher
{
MembershipProviderBase MembershipProvider { get; }
}
/// <summary>
/// A custom password hasher that conforms to the password hashing done with membership providers
/// </summary>
public class MembershipProviderPasswordHasher : IMembershipProviderPasswordHasher
{
/// <summary>
/// Exposes the underlying MembershipProvider
/// </summary>
public MembershipProviderBase MembershipProvider { get; private set; }
public MembershipProviderPasswordHasher(MembershipProviderBase provider)
{
MembershipProvider = provider;
}
public string HashPassword(string password)
{
return MembershipProvider.HashPasswordForStorage(password);
}
public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
return MembershipProvider.VerifyPassword(providedPassword, hashedPassword)
? PasswordVerificationResult.Success
: PasswordVerificationResult.Failed;
}
}
}

View File

@@ -663,7 +663,7 @@
<Compile Include="Security\BackOfficeUserStore.cs" />
<Compile Include="Security\IBackOfficeUserManagerMarker.cs" />
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
<Compile Include="Security\MembershipPasswordHasher.cs" />
<Compile Include="Security\MembershipProviderPasswordHasher.cs" />
<Compile Include="Security\EmailService.cs" />
<Compile Include="Security\MembershipProviderPasswordValidator.cs" />
<Compile Include="Security\OwinExtensions.cs" />

View File

@@ -56,7 +56,9 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
[WebApi.UmbracoAuthorize(requireApproval: false)]
public IDictionary<string, object> GetMembershipProviderConfig()
{
{
//TODO: Check if the current PasswordValidator is an IMembershipProviderPasswordValidator, if
//it's not than we should return some generic defaults
var provider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider();
return provider.GetConfiguration(Services.UserService);
}

View File

@@ -86,9 +86,10 @@ namespace Umbraco.Web.Editors
/// <returns>
/// If the password is being reset it will return the newly reset password, otherwise will return an empty value
/// </returns>
public ModelWithNotifications<string> PostChangePassword(ChangingPasswordModel data)
public async Task<ModelWithNotifications<string>> PostChangePassword(ChangingPasswordModel data)
{
var passwordChangeResult = PasswordChangeControllerHelper.ChangePassword(Security.CurrentUser, data, ModelState, Members);
var passwordChanger = new PasswordChanger(Logger, Services.UserService);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(Security.CurrentUser, data, ModelState, UserManager);
if (passwordChangeResult.Success)
{

View File

@@ -1,39 +0,0 @@
using System;
using System.Linq;
using System.Web.Http.ModelBinding;
using Umbraco.Core;
using Umbraco.Core.Models.Membership;
using Umbraco.Web.Models;
using Umbraco.Web.Security;
namespace Umbraco.Web.Editors
{
internal class PasswordChangeControllerHelper
{
public static Attempt<PasswordChangedModel> ChangePassword(
IUser currentUser,
ChangingPasswordModel data,
ModelStateDictionary modelState,
MembershipHelper membersHelper)
{
var userProvider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider();
if (userProvider.RequiresQuestionAndAnswer)
{
throw new NotSupportedException("Currently the user editor does not support providers that have RequiresQuestionAndAnswer specified");
}
var passwordChangeResult = membersHelper.ChangePassword(currentUser.Username, data, userProvider);
if (passwordChangeResult.Success == false)
{
//it wasn't successful, so add the change error to the model state
var fieldName = passwordChangeResult.Result.ChangeError.MemberNames.FirstOrDefault() ?? "password";
modelState.AddModelError(fieldName,
passwordChangeResult.Result.ChangeError.ErrorMessage);
}
return passwordChangeResult;
}
}
}

View File

@@ -0,0 +1,246 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http.ModelBinding;
using System.Web.Security;
using Microsoft.AspNet.Identity;
using umbraco.cms.businesslogic.packager;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Models;
using Umbraco.Web.Security;
using IUser = Umbraco.Core.Models.Membership.IUser;
namespace Umbraco.Web.Editors
{
internal class PasswordChanger
{
private readonly ILogger _logger;
private readonly IUserService _userService;
public PasswordChanger(ILogger logger, IUserService userService)
{
_logger = logger;
_userService = userService;
}
public async Task<Attempt<PasswordChangedModel>> ChangePasswordWithIdentityAsync(
IUser currentUser,
ChangingPasswordModel passwordModel,
ModelStateDictionary modelState,
BackOfficeUserManager<BackOfficeIdentityUser> userMgr)
{
if (passwordModel == null) throw new ArgumentNullException("passwordModel");
if (userMgr == null) throw new ArgumentNullException("userMgr");
//check if this identity implementation is powered by an underlying membership provider (it will be in most cases)
var membershipPasswordHasher = userMgr.PasswordHasher as IMembershipProviderPasswordHasher;
//check if this identity implementation is powered by an IUserAwarePasswordHasher (it will be by default in 7.7+ but not for upgrades)
var userAwarePasswordHasher = userMgr.PasswordHasher as IUserAwarePasswordHasher<int>;
if (membershipPasswordHasher != null && userAwarePasswordHasher == null)
{
//if this isn't using an IUserAwarePasswordHasher, then fallback to the old way
if (membershipPasswordHasher.MembershipProvider.RequiresQuestionAndAnswer)
throw new NotSupportedException("Currently the user editor does not support providers that have RequiresQuestionAndAnswer specified");
return ChangePasswordWithMembershipProvider(currentUser.Username, passwordModel, membershipPasswordHasher.MembershipProvider);
}
//get the real password validator, thsi should not be null but in some very rare cases it could be, in which case
//we need to create a default password validator to use since we have no idea what it actually is or what it's rules are
//this is an Edge Case!
var passwordValidator = userMgr.PasswordValidator as PasswordValidator
?? (membershipPasswordHasher != null
? new MembershipProviderPasswordValidator(membershipPasswordHasher.MembershipProvider)
: new PasswordValidator());
//Are we resetting the password??
if (passwordModel.Reset.HasValue && passwordModel.Reset.Value)
{
//ok, we should be able to reset it
var resetToken = await userMgr.GeneratePasswordResetTokenAsync(currentUser.Id);
var newPass = Membership.GeneratePassword(passwordValidator.RequiredLength, passwordValidator.RequireNonLetterOrDigit ? 2 : 0);
var resetResult = await userMgr.ResetPasswordAsync(currentUser.Id, resetToken, newPass);
if (resetResult.Succeeded == false)
{
var errors = string.Join(". ", resetResult.Errors);
_logger.Warn<PasswordChanger>(string.Format("Could not reset member password {0}", errors));
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, errors: " + errors, new[] { "resetPassword" }) });
}
return Attempt.Succeed(new PasswordChangedModel { ResetPassword = newPass });
}
//we're not resetting it so we need to try to change it.
if (passwordModel.NewPassword.IsNullOrWhiteSpace())
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Cannot set an empty password", new[] { "value" }) });
}
//we cannot arbitrarily change the password without knowing the old one and no old password was supplied - need to return an error
//TODO: What if the current user is admin? We should allow manually changing then?
if (passwordModel.OldPassword.IsNullOrWhiteSpace())
{
//if password retrieval is not enabled but there is no old password we cannot continue
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false)
{
//if an old password is suplied try to change it
var changeResult = await userMgr.ChangePasswordAsync(currentUser.Id, passwordModel.OldPassword, passwordModel.NewPassword);
if (changeResult.Succeeded == false)
{
var errors = string.Join(". ", changeResult.Errors);
_logger.Warn<PasswordChanger>(string.Format("Could not change member password {0}", errors));
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, errors: " + errors, new[] { "value" }) });
}
return Attempt.Succeed(new PasswordChangedModel());
}
//We shouldn't really get here
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid information supplied", new[] { "value" }) });
}
/// <summary>
/// Changes password for a member/user given the membership provider and the password change model
/// </summary>
/// <param name="username"></param>
/// <param name="passwordModel"></param>
/// <param name="membershipProvider"></param>
/// <returns></returns>
public Attempt<PasswordChangedModel> ChangePasswordWithMembershipProvider(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider)
{
// YES! It is completely insane how many options you have to take into account based on the membership provider. yikes!
if (passwordModel == null) throw new ArgumentNullException("passwordModel");
if (membershipProvider == null) throw new ArgumentNullException("membershipProvider");
//Are we resetting the password??
if (passwordModel.Reset.HasValue && passwordModel.Reset.Value)
{
var canReset = membershipProvider.CanResetPassword(_userService);
if (canReset == false)
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }) });
}
if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace())
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset requires a password answer", new[] { "resetPassword" }) });
}
//ok, we should be able to reset it
try
{
var newPass = membershipProvider.ResetPassword(
username,
membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null);
//return the generated pword
return Attempt.Succeed(new PasswordChangedModel { ResetPassword = newPass });
}
catch (Exception ex)
{
_logger.WarnWithException<PasswordChanger>("Could not reset member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, error: " + ex.Message + " (see log for full details)", new[] { "resetPassword" }) });
}
}
//we're not resetting it so we need to try to change it.
if (passwordModel.NewPassword.IsNullOrWhiteSpace())
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Cannot set an empty password", new[] { "value" }) });
}
//This is an edge case and is only necessary for backwards compatibility:
var umbracoBaseProvider = membershipProvider as MembershipProviderBase;
if (umbracoBaseProvider != null && umbracoBaseProvider.AllowManuallyChangingPassword)
{
//this provider allows manually changing the password without the old password, so we can just do it
try
{
var result = umbracoBaseProvider.ChangePassword(username, "", passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex)
{
_logger.WarnWithException<PasswordChanger>("Could not change member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) });
}
}
//The provider does not support manually chaning the password but no old password supplied - need to return an error
if (passwordModel.OldPassword.IsNullOrWhiteSpace() && membershipProvider.EnablePasswordRetrieval == false)
{
//if password retrieval is not enabled but there is no old password we cannot continue
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false)
{
//if an old password is suplied try to change it
try
{
var result = membershipProvider.ChangePassword(username, passwordModel.OldPassword, passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "oldPassword" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex)
{
_logger.WarnWithException<PasswordChanger>("Could not change member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) });
}
}
if (membershipProvider.EnablePasswordRetrieval == false)
{
//we cannot continue if we cannot get the current password
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace())
{
//if the question answer is required but there isn't one, we cannot continue
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the password answer", new[] { "value" }) });
}
//lets try to get the old one so we can change it
try
{
var oldPassword = membershipProvider.GetPassword(
username,
membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null);
try
{
var result = membershipProvider.ChangePassword(username, oldPassword, passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password", new[] { "value" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex1)
{
_logger.WarnWithException<PasswordChanger>("Could not change member password", ex1);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex1.Message + " (see log for full details)", new[] { "value" }) });
}
}
catch (Exception ex2)
{
_logger.WarnWithException<PasswordChanger>("Could not retrieve member password", ex2);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex2.Message + " (see log for full details)", new[] { "value" }) });
}
}
}
}

View File

@@ -404,7 +404,7 @@ namespace Umbraco.Web.Editors
/// </summary>
/// <param name="userSave"></param>
/// <returns></returns>
public UserDisplay PostSaveUser(UserSave userSave)
public async Task<UserDisplay> PostSaveUser(UserSave userSave)
{
if (userSave == null) throw new ArgumentNullException("userSave");
@@ -460,7 +460,9 @@ namespace Umbraco.Web.Editors
var resetPasswordValue = string.Empty;
if (userSave.ChangePassword != null)
{
var passwordChangeResult = PasswordChangeControllerHelper.ChangePassword(found, userSave.ChangePassword, ModelState, Members);
var passwordChanger = new PasswordChanger(Logger, Services.UserService);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(found, userSave.ChangePassword, ModelState, UserManager);
if (passwordChangeResult.Success)
{
//depending on how the provider is configured, the password may be reset so let's store that for later

View File

@@ -32,6 +32,7 @@ namespace Umbraco.Web.Install.InstallSteps
_applicationContext = applicationContext;
}
//TODO: Change all logic in this step to use ASP.NET Identity NOT MembershipProviders
private MembershipProvider CurrentProvider
{
get

View File

@@ -13,6 +13,7 @@ using Umbraco.Core.Security;
using Umbraco.Web.Models;
using Umbraco.Web.PublishedCache;
using Umbraco.Core.Cache;
using Umbraco.Web.Editors;
using Umbraco.Web.Security.Providers;
using MPE = global::Umbraco.Core.Security.MembershipProviderExtensions;
@@ -655,128 +656,8 @@ namespace Umbraco.Web.Security
/// <returns></returns>
public virtual Attempt<PasswordChangedModel> ChangePassword(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider)
{
// YES! It is completely insane how many options you have to take into account based on the membership provider. yikes!
if (passwordModel == null) throw new ArgumentNullException("passwordModel");
if (membershipProvider == null) throw new ArgumentNullException("membershipProvider");
//Are we resetting the password??
if (passwordModel.Reset.HasValue && passwordModel.Reset.Value)
{
var canReset = membershipProvider.CanResetPassword(_applicationContext.Services.UserService);
if (canReset == false)
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }) });
}
if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace())
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset requires a password answer", new[] { "resetPassword" }) });
}
//ok, we should be able to reset it
try
{
var newPass = membershipProvider.ResetPassword(
username,
membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null);
//return the generated pword
return Attempt.Succeed(new PasswordChangedModel { ResetPassword = newPass });
}
catch (Exception ex)
{
LogHelper.WarnWithException<WebSecurity>("Could not reset member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, error: " + ex.Message + " (see log for full details)", new[] { "resetPassword" }) });
}
}
//we're not resetting it so we need to try to change it.
if (passwordModel.NewPassword.IsNullOrWhiteSpace())
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Cannot set an empty password", new[] { "value" }) });
}
//This is an edge case and is only necessary for backwards compatibility:
var umbracoBaseProvider = membershipProvider as MembershipProviderBase;
if (umbracoBaseProvider != null && umbracoBaseProvider.AllowManuallyChangingPassword)
{
//this provider allows manually changing the password without the old password, so we can just do it
try
{
var result = umbracoBaseProvider.ChangePassword(username, "", passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex)
{
LogHelper.WarnWithException<WebSecurity>("Could not change member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) });
}
}
//The provider does not support manually chaning the password but no old password supplied - need to return an error
if (passwordModel.OldPassword.IsNullOrWhiteSpace() && membershipProvider.EnablePasswordRetrieval == false)
{
//if password retrieval is not enabled but there is no old password we cannot continue
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false)
{
//if an old password is suplied try to change it
try
{
var result = membershipProvider.ChangePassword(username, passwordModel.OldPassword, passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "oldPassword" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex)
{
LogHelper.WarnWithException<WebSecurity>("Could not change member password", ex);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) });
}
}
if (membershipProvider.EnablePasswordRetrieval == false)
{
//we cannot continue if we cannot get the current password
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "oldPassword" }) });
}
if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace())
{
//if the question answer is required but there isn't one, we cannot continue
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the password answer", new[] { "value" }) });
}
//lets try to get the old one so we can change it
try
{
var oldPassword = membershipProvider.GetPassword(
username,
membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null);
try
{
var result = membershipProvider.ChangePassword(username, oldPassword, passwordModel.NewPassword);
return result == false
? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password", new[] { "value" }) })
: Attempt.Succeed(new PasswordChangedModel());
}
catch (Exception ex1)
{
LogHelper.WarnWithException<WebSecurity>("Could not change member password", ex1);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex1.Message + " (see log for full details)", new[] { "value" }) });
}
}
catch (Exception ex2)
{
LogHelper.WarnWithException<WebSecurity>("Could not retrieve member password", ex2);
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex2.Message + " (see log for full details)", new[] { "value" }) });
}
var passwordChanger = new PasswordChanger(_applicationContext.ProfilingLogger.Logger, _applicationContext.Services.UserService);
return passwordChanger.ChangePasswordWithMembershipProvider(username, passwordModel, membershipProvider);
}
/// <summary>

View File

@@ -170,10 +170,14 @@ namespace Umbraco.Web.Security
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
/// <remarks>
/// This uses ASP.NET Identity to perform the validation
/// </remarks>
public virtual bool ValidateBackOfficeCredentials(string username, string password)
{
var membershipProvider = Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider();
return membershipProvider != null && membershipProvider.ValidateUser(username, password);
var backofficeuser = Mapper.Map<BackOfficeIdentityUser>(CurrentUser);
backofficeuser.UserName = username;
return UserManager.CheckPasswordAsync(backofficeuser, password).Result;
}
/// <summary>

View File

@@ -333,7 +333,7 @@
<Compile Include="Editors\EditorValidator.cs" />
<Compile Include="Editors\FromJsonPathAttribute.cs" />
<Compile Include="Editors\IsCurrentUserModelFilterAttribute.cs" />
<Compile Include="Editors\PasswordChangeControllerHelper.cs" />
<Compile Include="Editors\PasswordChanger.cs" />
<Compile Include="Editors\TemplateController.cs" />
<Compile Include="Editors\ParameterSwapControllerActionSelector.cs" />
<Compile Include="Editors\CodeFileController.cs" />