Merge remote-tracking branch 'origin/dev-v7' into dev-v7.7, removes the UnlockUser method of BackOfficeUserManager since the membership provider is no longer used to perform any unlocking
This commit is contained in:
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Auditing
|
||||
/// <summary>
|
||||
/// The action that got triggered from the audit event
|
||||
/// </summary>
|
||||
public AuditEvent Action { get; set; }
|
||||
public AuditEvent Action { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current date/time in UTC format
|
||||
@@ -23,27 +23,27 @@ namespace Umbraco.Core.Auditing
|
||||
/// <summary>
|
||||
/// The source IP address of the user performing the action
|
||||
/// </summary>
|
||||
public string IpAddress { get; set; }
|
||||
public string IpAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user affected by the event raised
|
||||
/// </summary>
|
||||
public int AffectedUser { get; set; }
|
||||
public int AffectedUser { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a user is perfoming an action on a different user, then this will be set. Otherwise it will be -1
|
||||
/// </summary>
|
||||
public int PerformingUser { get; set; }
|
||||
public int PerformingUser { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional comment about the action being logged
|
||||
/// </summary>
|
||||
public string Comment { get; set; }
|
||||
public string Comment { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This property is always empty except in the LoginFailed event for an unknown user trying to login
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
public string Username { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the properties on the event being raised, all parameters are optional except for the action being performed
|
||||
@@ -51,28 +51,26 @@ namespace Umbraco.Core.Auditing
|
||||
/// <param name="action">An action based on the AuditEvent enum</param>
|
||||
/// <param name="ipAddress">The client's IP address. This is usually automatically set but could be overridden if necessary</param>
|
||||
/// <param name="performingUser">The Id of the user performing the action (if different from the user affected by the action)</param>
|
||||
public IdentityAuditEventArgs(AuditEvent action, string ipAddress = "", int performingUser = -1)
|
||||
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, int performingUser = -1)
|
||||
{
|
||||
DateTimeUtc = DateTime.UtcNow;
|
||||
Action = action;
|
||||
|
||||
IpAddress = string.IsNullOrWhiteSpace(ipAddress)
|
||||
? GetCurrentRequestIpAddress()
|
||||
: ipAddress;
|
||||
IpAddress = ipAddress;
|
||||
|
||||
PerformingUser = performingUser == -1
|
||||
? GetCurrentRequestBackofficeUserId()
|
||||
: performingUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current request IP address for logging if there is one
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected string GetCurrentRequestIpAddress()
|
||||
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment)
|
||||
{
|
||||
var httpContext = HttpContext.Current == null ? (HttpContextBase)null : new HttpContextWrapper(HttpContext.Current);
|
||||
return httpContext.GetCurrentRequestIpAddress();
|
||||
DateTimeUtc = DateTime.UtcNow;
|
||||
Action = action;
|
||||
|
||||
IpAddress = ipAddress;
|
||||
Username = username;
|
||||
Comment = comment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Security;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Microsoft.Owin.Security.DataProtection;
|
||||
@@ -506,52 +507,23 @@ namespace Umbraco.Core.Security
|
||||
|
||||
public override async Task<IdentityResult> ResetAccessFailedCountAsync(int userId)
|
||||
{
|
||||
var user = ApplicationContext.Current.Services.UserService.GetUserById(userId);
|
||||
|
||||
var lockoutStore = (IUserLockoutStore<BackOfficeIdentityUser, int>)Store;
|
||||
var user = await FindByIdAsync(userId);
|
||||
if (user == null)
|
||||
{
|
||||
throw new ProviderException(string.Format("No user with the id {0} found", userId));
|
||||
}
|
||||
throw new InvalidOperationException("No user found by user id " + userId);
|
||||
|
||||
if (user.FailedPasswordAttempts > 0)
|
||||
{
|
||||
user.FailedPasswordAttempts = 0;
|
||||
ApplicationContext.Current.Services.UserService.Save(user);
|
||||
RaiseResetAccessFailedCountEvent(userId);
|
||||
}
|
||||
var accessFailedCount = await GetAccessFailedCountAsync(user.Id);
|
||||
|
||||
return await Task.FromResult(IdentityResult.Success);
|
||||
if (accessFailedCount == 0)
|
||||
return IdentityResult.Success;
|
||||
|
||||
await lockoutStore.ResetAccessFailedCountAsync(user);
|
||||
//raise the event now that it's reset
|
||||
RaiseResetAccessFailedCountEvent(userId);
|
||||
return await UpdateAsync(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears a lock so that the membership user can be validated.
|
||||
/// </summary>
|
||||
/// <param name="memberService">The IMemberService to user for unlocking</param>
|
||||
/// <param name="username">The membership user to clear the lock status for.</param>
|
||||
/// <returns>
|
||||
/// true if the membership user was successfully unlocked; otherwise, false.
|
||||
/// </returns>
|
||||
public bool UnlockUser<TEntity>(IMembershipMemberService<TEntity> memberService, string username) where TEntity : class, IMembershipUser
|
||||
{
|
||||
var member = memberService.GetByUsername(username);
|
||||
|
||||
if (member == null)
|
||||
{
|
||||
throw new ProviderException(string.Format("No member with the username '{0}' found", username));
|
||||
}
|
||||
|
||||
// Non need to update
|
||||
if (member.IsLockedOut == false) return true;
|
||||
|
||||
member.IsLockedOut = false;
|
||||
member.FailedPasswordAttempts = 0;
|
||||
|
||||
memberService.Save(member);
|
||||
|
||||
RaiseAccountUnlockedEvent(member.Id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public override Task<IdentityResult> AccessFailedAsync(int userId)
|
||||
{
|
||||
@@ -566,98 +538,61 @@ namespace Umbraco.Core.Security
|
||||
|
||||
internal void RaiseAccountLockedEvent(int userId)
|
||||
{
|
||||
OnAccountLocked(new IdentityAuditEventArgs(AuditEvent.AccountLocked)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnAccountLocked(new IdentityAuditEventArgs(AuditEvent.AccountLocked, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaiseAccountUnlockedEvent(int userId)
|
||||
{
|
||||
OnAccountUnlocked(new IdentityAuditEventArgs(AuditEvent.AccountUnlocked)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnAccountUnlocked(new IdentityAuditEventArgs(AuditEvent.AccountUnlocked, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaiseForgotPasswordRequestedEvent(int userId)
|
||||
{
|
||||
OnForgotPasswordRequested(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordRequested)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnForgotPasswordRequested(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordRequested, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaiseForgotPasswordChangedSuccessEvent(int userId)
|
||||
{
|
||||
OnForgotPasswordChangedSuccess(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordChangedSuccess)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnForgotPasswordChangedSuccess(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordChangedSuccess, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
public void RaiseLoginFailedEvent(int userId)
|
||||
internal void RaiseLoginFailedEvent(int userId)
|
||||
{
|
||||
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
public void RaiseInvalidLoginAttemptEvent(string username)
|
||||
internal void RaiseInvalidLoginAttemptEvent(string username)
|
||||
{
|
||||
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed)
|
||||
{
|
||||
Username = username,
|
||||
Comment = string.Format("Attempted login for username '{0}' failed", username)
|
||||
});
|
||||
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed, GetCurrentRequestIpAddress(), username, string.Format("Attempted login for username '{0}' failed", username)));
|
||||
}
|
||||
|
||||
internal void RaiseLoginRequiresVerificationEvent(int userId)
|
||||
{
|
||||
OnLoginRequiresVerification(new IdentityAuditEventArgs(AuditEvent.LoginRequiresVerification)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnLoginRequiresVerification(new IdentityAuditEventArgs(AuditEvent.LoginRequiresVerification, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaiseLoginSuccessEvent(int userId)
|
||||
{
|
||||
OnLoginSuccess(new IdentityAuditEventArgs(AuditEvent.LoginSucces)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnLoginSuccess(new IdentityAuditEventArgs(AuditEvent.LoginSucces, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaiseLogoutSuccessEvent(int userId)
|
||||
{
|
||||
OnLogoutSuccess(new IdentityAuditEventArgs(AuditEvent.LogoutSuccess)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnLogoutSuccess(new IdentityAuditEventArgs(AuditEvent.LogoutSuccess, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaisePasswordChangedEvent(int userId)
|
||||
{
|
||||
OnPasswordChanged(new IdentityAuditEventArgs(AuditEvent.PasswordChanged)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnPasswordChanged(new IdentityAuditEventArgs(AuditEvent.PasswordChanged, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
internal void RaisePasswordResetEvent(int userId)
|
||||
{
|
||||
OnPasswordReset(new IdentityAuditEventArgs(AuditEvent.PasswordReset)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnPasswordReset(new IdentityAuditEventArgs(AuditEvent.PasswordReset, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
internal void RaiseResetAccessFailedCountEvent(int userId)
|
||||
{
|
||||
OnResetAccessFailedCount(new IdentityAuditEventArgs(AuditEvent.ResetAccessFailedCount)
|
||||
{
|
||||
AffectedUser = userId
|
||||
});
|
||||
OnResetAccessFailedCount(new IdentityAuditEventArgs(AuditEvent.ResetAccessFailedCount, GetCurrentRequestIpAddress(), userId));
|
||||
}
|
||||
|
||||
public static event EventHandler AccountLocked;
|
||||
@@ -726,5 +661,16 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
if (ResetAccessFailedCount != null) ResetAccessFailedCount(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current request IP address for logging if there is one
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual string GetCurrentRequestIpAddress()
|
||||
{
|
||||
//TODO: inject a service to get this value, we should not be relying on the old HttpContext.Current especially in the ASP.NET Identity world.
|
||||
var httpContext = HttpContext.Current == null ? (HttpContextBase)null : new HttpContextWrapper(HttpContext.Current);
|
||||
return httpContext.GetCurrentRequestIpAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,18 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (passwordChangeResult.Success)
|
||||
{
|
||||
var userMgr = this.TryGetOwinContext().Result.GetBackOfficeUserManager();
|
||||
|
||||
//raise the appropriate event
|
||||
if (data.Reset.HasValue && data.Reset.Value)
|
||||
{
|
||||
userMgr.RaisePasswordResetEvent(Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
userMgr.RaisePasswordChangedEvent(Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
//even if we weren't resetting this, it is the correct value (null), otherwise if we were resetting then it will contain the new pword
|
||||
var result = new ModelWithNotifications<string>(passwordChangeResult.Result.ResetPassword);
|
||||
result.AddSuccessNotification(Services.TextService.Localize("user/password"), Services.TextService.Localize("user/passwordChanged"));
|
||||
|
||||
@@ -17,7 +17,7 @@ using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Web.Security.Providers
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Abstract Membership Provider that users any implementation of IMembershipMemberService{TEntity} service
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
{
|
||||
|
||||
protected IMembershipMemberService<TEntity> MemberService { get; private set; }
|
||||
|
||||
|
||||
protected UmbracoMembershipProvider(IMembershipMemberService<TEntity> memberService)
|
||||
{
|
||||
MemberService = memberService;
|
||||
@@ -60,7 +60,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
/// <exception cref="T:System.ArgumentException">The name of the provider has a length of zero.</exception>
|
||||
public override void Initialize(string name, NameValueCollection config)
|
||||
{
|
||||
if (config == null) {throw new ArgumentNullException("config");}
|
||||
if (config == null) { throw new ArgumentNullException("config"); }
|
||||
|
||||
if (string.IsNullOrEmpty(name)) name = ProviderName;
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
// in order to support updating passwords from the umbraco core, we can't validate the old password
|
||||
var m = MemberService.GetByUsername(username);
|
||||
if (m == null) return false;
|
||||
|
||||
|
||||
string salt;
|
||||
var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
protected override MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
|
||||
protected override MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
|
||||
string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
// See if the user already exists
|
||||
@@ -166,11 +166,11 @@ namespace Umbraco.Web.Security.Providers
|
||||
|
||||
var member = MemberService.CreateWithIdentity(
|
||||
username,
|
||||
email,
|
||||
FormatPasswordForStorage(encodedPassword, salt),
|
||||
email,
|
||||
FormatPasswordForStorage(encodedPassword, salt),
|
||||
memberTypeAlias,
|
||||
isApproved);
|
||||
|
||||
|
||||
member.PasswordQuestion = passwordQuestion;
|
||||
member.RawPasswordAnswerValue = EncryptString(passwordAnswer);
|
||||
member.LastLoginDate = DateTime.Now;
|
||||
@@ -214,7 +214,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
var byEmail = MemberService.FindByEmail(emailToMatch, pageIndex, pageSize, out totalRecords, StringPropertyMatchType.Wildcard).ToArray();
|
||||
|
||||
|
||||
var collection = new MembershipUserCollection();
|
||||
foreach (var m in byEmail)
|
||||
{
|
||||
@@ -259,7 +259,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
var membersList = new MembershipUserCollection();
|
||||
|
||||
var pagedMembers = MemberService.GetAll(pageIndex, pageSize, out totalRecords);
|
||||
|
||||
|
||||
foreach (var m in pagedMembers)
|
||||
{
|
||||
membersList.Add(ConvertToMembershipUser(m));
|
||||
@@ -292,7 +292,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
/// The password for the specified user name.
|
||||
/// </returns>
|
||||
protected override string PerformGetPassword(string username, string answer)
|
||||
{
|
||||
{
|
||||
var m = MemberService.GetByUsername(username);
|
||||
if (m == null)
|
||||
{
|
||||
@@ -414,7 +414,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
// UpdateFailureCount(username, "passwordAnswer");
|
||||
// throw new ProviderException("Password answer required for password reset.");
|
||||
//}
|
||||
|
||||
|
||||
var m = MemberService.GetByUsername(username);
|
||||
if (m == null)
|
||||
{
|
||||
@@ -438,7 +438,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
m.RawPasswordValue = FormatPasswordForStorage(encodedPassword, salt);
|
||||
m.LastPasswordChangeDate = DateTime.Now;
|
||||
MemberService.Save(m);
|
||||
|
||||
|
||||
return generatedPassword;
|
||||
}
|
||||
|
||||
@@ -451,15 +451,21 @@ namespace Umbraco.Web.Security.Providers
|
||||
/// </returns>
|
||||
public override bool UnlockUser(string username)
|
||||
{
|
||||
var userManager = GetBackofficeUserManager();
|
||||
return userManager != null && userManager.UnlockUser(MemberService, username);
|
||||
}
|
||||
var member = MemberService.GetByUsername(username);
|
||||
if (member == null)
|
||||
{
|
||||
throw new ProviderException(string.Format("No member with the username '{0}' found", username));
|
||||
}
|
||||
|
||||
internal BackOfficeUserManager<BackOfficeIdentityUser> GetBackofficeUserManager()
|
||||
{
|
||||
return HttpContext.Current == null
|
||||
? null
|
||||
: HttpContext.Current.GetOwinContext().GetBackOfficeUserManager();
|
||||
// Non need to update
|
||||
if (member.IsLockedOut == false) return true;
|
||||
|
||||
member.IsLockedOut = false;
|
||||
member.FailedPasswordAttempts = 0;
|
||||
|
||||
MemberService.Save(member);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -485,7 +491,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
}
|
||||
}
|
||||
m.Email = user.Email;
|
||||
|
||||
|
||||
m.IsApproved = user.IsApproved;
|
||||
m.IsLockedOut = user.IsLockedOut;
|
||||
if (user.IsLockedOut)
|
||||
@@ -497,15 +503,9 @@ namespace Umbraco.Web.Security.Providers
|
||||
MemberService.Save(m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified user name and password exist in the data source.
|
||||
/// </summary>
|
||||
/// <param name="username">The name of the user to validate.</param>
|
||||
/// <param name="password">The password for the specified user.</param>
|
||||
/// <returns>
|
||||
/// true if the specified username and password are valid; otherwise, false.
|
||||
/// </returns>
|
||||
public override bool ValidateUser(string username, string password)
|
||||
|
||||
|
||||
internal virtual ValidateUserResult PerformValidateUser(string username, string password)
|
||||
{
|
||||
var member = MemberService.GetByUsername(username);
|
||||
|
||||
@@ -517,7 +517,10 @@ namespace Umbraco.Web.Security.Providers
|
||||
username,
|
||||
GetCurrentRequestIpAddress()));
|
||||
|
||||
return false;
|
||||
return new ValidateUserResult
|
||||
{
|
||||
Authenticated = false
|
||||
};
|
||||
}
|
||||
|
||||
if (member.IsApproved == false)
|
||||
@@ -528,7 +531,11 @@ namespace Umbraco.Web.Security.Providers
|
||||
username,
|
||||
GetCurrentRequestIpAddress()));
|
||||
|
||||
return false;
|
||||
return new ValidateUserResult
|
||||
{
|
||||
Member = member,
|
||||
Authenticated = false
|
||||
};
|
||||
}
|
||||
if (member.IsLockedOut)
|
||||
{
|
||||
@@ -538,11 +545,14 @@ namespace Umbraco.Web.Security.Providers
|
||||
username,
|
||||
GetCurrentRequestIpAddress()));
|
||||
|
||||
return false;
|
||||
return new ValidateUserResult
|
||||
{
|
||||
Member = member,
|
||||
Authenticated = false
|
||||
};
|
||||
}
|
||||
|
||||
var authenticated = CheckPassword(password, member.RawPasswordValue);
|
||||
var backofficeUserManager = GetBackofficeUserManager();
|
||||
|
||||
if (authenticated == false)
|
||||
{
|
||||
@@ -561,10 +571,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
string.Format(
|
||||
"Login attempt failed for username {0} from IP address {1}, the user is now locked out, max invalid password attempts exceeded",
|
||||
username,
|
||||
GetCurrentRequestIpAddress()));
|
||||
|
||||
if(backofficeUserManager != null)
|
||||
backofficeUserManager.RaiseAccountLockedEvent(member.Id);
|
||||
GetCurrentRequestIpAddress()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -581,8 +588,6 @@ namespace Umbraco.Web.Security.Providers
|
||||
{
|
||||
//we have successfully logged in, reset the AccessFailedCount
|
||||
member.FailedPasswordAttempts = 0;
|
||||
if (backofficeUserManager != null)
|
||||
backofficeUserManager.RaiseResetAccessFailedCountEvent(member.Id);
|
||||
}
|
||||
|
||||
member.LastLoginDate = DateTime.Now;
|
||||
@@ -591,10 +596,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
string.Format(
|
||||
"Login attempt succeeded for username {0} from IP address {1}",
|
||||
username,
|
||||
GetCurrentRequestIpAddress()));
|
||||
|
||||
if (backofficeUserManager != null)
|
||||
backofficeUserManager.RaiseLoginSuccessEvent(member.Id);
|
||||
GetCurrentRequestIpAddress()));
|
||||
}
|
||||
|
||||
//don't raise events for this! It just sets the member dates, if we do raise events this will
|
||||
@@ -607,7 +609,31 @@ namespace Umbraco.Web.Security.Providers
|
||||
if (UmbracoVersion.Current >= new Version(7, 3, 0, 0))
|
||||
MemberService.Save(member, false);
|
||||
|
||||
return authenticated;
|
||||
return new ValidateUserResult
|
||||
{
|
||||
Authenticated = authenticated,
|
||||
Member = member
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the specified user name and password exist in the data source.
|
||||
/// </summary>
|
||||
/// <param name="username">The name of the user to validate.</param>
|
||||
/// <param name="password">The password for the specified user.</param>
|
||||
/// <returns>
|
||||
/// true if the specified username and password are valid; otherwise, false.
|
||||
/// </returns>
|
||||
public override bool ValidateUser(string username, string password)
|
||||
{
|
||||
var result = PerformValidateUser(username, password);
|
||||
return result.Authenticated;
|
||||
}
|
||||
|
||||
internal class ValidateUserResult
|
||||
{
|
||||
public TEntity Member { get; set; }
|
||||
public bool Authenticated { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
using System.Configuration.Provider;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -115,5 +117,49 @@ namespace Umbraco.Web.Security.Providers
|
||||
return _defaultMemberTypeAlias;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override in order to raise appropriate events via the <see cref="BackOfficeUserManager"/>
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
internal override ValidateUserResult PerformValidateUser(string username, string password)
|
||||
{
|
||||
var result = base.PerformValidateUser(username, password);
|
||||
|
||||
var userManager = GetBackofficeUserManager();
|
||||
|
||||
if (userManager == null) return result;
|
||||
|
||||
if (result.Authenticated == false)
|
||||
{
|
||||
var count = result.Member.FailedPasswordAttempts;
|
||||
if (count >= MaxInvalidPasswordAttempts)
|
||||
{
|
||||
userManager.RaiseAccountLockedEvent(result.Member.Id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result.Member.FailedPasswordAttempts > 0)
|
||||
{
|
||||
//we have successfully logged in, if the failed password attempts was modified it means it was reset
|
||||
if (result.Member.WasPropertyDirty("FailedPasswordAttempts"))
|
||||
{
|
||||
userManager.RaiseResetAccessFailedCountEvent(result.Member.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal BackOfficeUserManager<BackOfficeIdentityUser> GetBackofficeUserManager()
|
||||
{
|
||||
return HttpContext.Current == null
|
||||
? null
|
||||
: HttpContext.Current.GetOwinContext().GetBackOfficeUserManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user