Lots more unit tests for the membership providers and some other fixups - have a new failing test as i need to sort out salting issue with encrypted passwords.
This commit is contained in:
@@ -11,76 +11,6 @@ using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
|
||||
public abstract class UmbracoMembershipProviderBase : MembershipProviderBase
|
||||
{
|
||||
protected UmbracoMembershipProviderBase()
|
||||
{
|
||||
//Set the defaults!
|
||||
DefaultMemberTypeAlias = "Member";
|
||||
}
|
||||
|
||||
public string DefaultMemberTypeAlias { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
protected sealed override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
return PerformCreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="memberTypeAlias">The member type alias to use when creating the member</param>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
//do the base validation first
|
||||
base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
|
||||
return PerformCreateUser(memberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="memberTypeAlias">The member type alias to use when creating the member</param>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
protected abstract MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
|
||||
}
|
||||
/// <summary>
|
||||
/// A base membership provider class offering much of the underlying functionality for initializing and password encryption/hashing.
|
||||
/// </summary>
|
||||
@@ -741,7 +671,7 @@ namespace Umbraco.Core.Security
|
||||
/// <param name="newPassword"></param>
|
||||
/// <param name="salt"></param>
|
||||
/// <returns></returns>
|
||||
protected string EncryptOrHashNewPassword(string newPassword, out string salt)
|
||||
protected internal string EncryptOrHashNewPassword(string newPassword, out string salt)
|
||||
{
|
||||
salt = GenerateSalt();
|
||||
return EncryptOrHashPassword(newPassword, salt);
|
||||
|
||||
78
src/Umbraco.Core/Security/UmbracoMembershipProviderBase.cs
Normal file
78
src/Umbraco.Core/Security/UmbracoMembershipProviderBase.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A base membership provider class for umbraco members (not users)
|
||||
/// </summary>
|
||||
public abstract class UmbracoMembershipProviderBase : MembershipProviderBase
|
||||
{
|
||||
protected UmbracoMembershipProviderBase()
|
||||
{
|
||||
//Set the defaults!
|
||||
DefaultMemberTypeAlias = "Member";
|
||||
}
|
||||
|
||||
public string DefaultMemberTypeAlias { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
protected sealed override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
return PerformCreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="memberTypeAlias">The member type alias to use when creating the member</param>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
//do the base validation first
|
||||
base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
|
||||
return PerformCreateUser(memberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new membership user to the data source.
|
||||
/// </summary>
|
||||
/// <param name="memberTypeAlias">The member type alias to use when creating the member</param>
|
||||
/// <param name="username">The user name for the new user.</param>
|
||||
/// <param name="password">The password for the new user.</param>
|
||||
/// <param name="email">The e-mail address for the new user.</param>
|
||||
/// <param name="passwordQuestion">The password question for the new user.</param>
|
||||
/// <param name="passwordAnswer">The password answer for the new user</param>
|
||||
/// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
|
||||
/// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
|
||||
/// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
|
||||
/// </returns>
|
||||
protected abstract MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Defines the MemberService, which is an easy access to operations involving (umbraco) members.
|
||||
/// </summary>
|
||||
internal interface IMemberService : IMembershipMemberService
|
||||
public interface IMemberService : IMembershipMemberService
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if a member with the id exists
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Services
|
||||
/// <remarks>
|
||||
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
|
||||
/// </remarks>
|
||||
internal interface IMembershipMemberService : IService
|
||||
public interface IMembershipMemberService : IService
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if a member with the username exists
|
||||
|
||||
@@ -741,6 +741,7 @@
|
||||
<Compile Include="Security\AuthenticationExtensions.cs" />
|
||||
<Compile Include="Security\MembershipProviderBase.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
|
||||
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
|
||||
<Compile Include="Security\UserData.cs" />
|
||||
<Compile Include="Serialization\AbstractSerializationService.cs" />
|
||||
<Compile Include="Serialization\Formatter.cs" />
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
</system.data>
|
||||
|
||||
<system.web>
|
||||
<machineKey validationKey="5E7B955FCE36F5F2A867C2A0D85DC61E7FEA9E15F1561E8386F78BFE9EE23FF18B21E6A44AA17300B3B9D5DBEB37AA61A2C73884A5BBEDA6D3B14BA408A7A8CD" decryptionKey="116B853D031219E404E088FCA0986D6CF2DFA77E1957B59FCC9404B8CA3909A1" validation="SHA1" decryption="AES" />
|
||||
<!--<trust level="Medium" originUrl=".*"/>-->
|
||||
<!-- Sitemap provider-->
|
||||
<siteMap defaultProvider="UmbracoSiteMapProvider" enabled="true">
|
||||
|
||||
@@ -7,8 +7,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Security;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using Umbraco.Web.Security.Providers;
|
||||
|
||||
namespace Umbraco.Tests.Membership
|
||||
@@ -20,31 +25,243 @@ namespace Umbraco.Tests.Membership
|
||||
//public void Set_Default_Member_Type_On_Init()
|
||||
|
||||
//[Test]
|
||||
//public void Question_Answer_Is_Encrypted()
|
||||
//public void Create_User_Already_Exists()
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Create_User_Requires_Unique_Email()
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void Answer_Is_Encrypted()
|
||||
{
|
||||
IMember createdMember = null;
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
|
||||
{
|
||||
memberType.AddPropertyType(p.Value);
|
||||
}
|
||||
var mServiceMock = new Mock<IMemberService>();
|
||||
mServiceMock.Setup(service => service.Exists("test")).Returns(false);
|
||||
mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
|
||||
mServiceMock.Setup(
|
||||
service => service.CreateMember(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Callback((string u, string e, string p, string m) =>
|
||||
{
|
||||
createdMember = new Member("test", e, u, p, memberType);
|
||||
})
|
||||
.Returns(() => createdMember);
|
||||
var provider = new MembersMembershipProvider(mServiceMock.Object);
|
||||
|
||||
MembershipCreateStatus status;
|
||||
provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
|
||||
|
||||
Assert.AreNotEqual("test", createdMember.PasswordAnswer);
|
||||
Assert.AreEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Password_Encrypted_With_Salt()
|
||||
{
|
||||
IMember createdMember = null;
|
||||
var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
|
||||
{
|
||||
memberType.AddPropertyType(p.Value);
|
||||
}
|
||||
var mServiceMock = new Mock<IMemberService>();
|
||||
mServiceMock.Setup(service => service.Exists("test")).Returns(false);
|
||||
mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
|
||||
mServiceMock.Setup(
|
||||
service => service.CreateMember(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Callback((string u, string e, string p, string m) =>
|
||||
{
|
||||
createdMember = new Member("test", e, u, p, memberType);
|
||||
})
|
||||
.Returns(() => createdMember);
|
||||
|
||||
var provider = new MembersMembershipProvider(mServiceMock.Object);
|
||||
provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Encrypted" } });
|
||||
MembershipCreateStatus status;
|
||||
provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
|
||||
|
||||
Assert.AreNotEqual("test", createdMember.Password);
|
||||
//Assert.AreNotEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
|
||||
string salt;
|
||||
var encodedPassword = provider.EncryptOrHashNewPassword("test", out salt);
|
||||
Assert.AreEqual(encodedPassword, createdMember.Password);
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void Password_Hashed_With_Salt()
|
||||
//{
|
||||
// IMember createdMember = null;
|
||||
// var memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
// foreach (var p in Constants.Conventions.Member.GetStandardPropertyTypeStubs())
|
||||
// {
|
||||
// memberType.AddPropertyType(p.Value);
|
||||
// }
|
||||
// var mServiceMock = new Mock<IMemberService>();
|
||||
// mServiceMock.Setup(service => service.Exists("test")).Returns(false);
|
||||
// mServiceMock.Setup(service => service.GetByEmail("test@test.com")).Returns(() => null);
|
||||
// mServiceMock.Setup(
|
||||
// service => service.CreateMember(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||
// .Callback((string u, string e, string p, string m) =>
|
||||
// {
|
||||
// createdMember = new Member("test", e, u, p, memberType);
|
||||
// })
|
||||
// .Returns(() => createdMember);
|
||||
|
||||
// var provider = new MembersMembershipProvider(mServiceMock.Object);
|
||||
// provider.Initialize("test", new NameValueCollection { { "passwordFormat", "Hashed" } });
|
||||
// MembershipCreateStatus status;
|
||||
// provider.CreateUser("test", "test", "test", "test@test.com", "test", "test", true, "test", out status);
|
||||
|
||||
// Assert.AreNotEqual("test", createdMember.Password);
|
||||
// Assert.AreNotEqual(provider.EncryptString("test"), createdMember.PasswordAnswer);
|
||||
// string salt;
|
||||
// var encodedPassword = provider.EncryptOrHashNewPassword("test", out salt);
|
||||
// Assert.AreEqual(encodedPassword, createdMember.Password);
|
||||
//}
|
||||
|
||||
//[Test]
|
||||
//public void Password_Encrypted_Validated_With_Salt()
|
||||
|
||||
//[Test]
|
||||
//public void Password_Encrypted_Validated_With_Salt()
|
||||
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class MembershipProviderBaseTests
|
||||
{
|
||||
//[Test]
|
||||
//public void Change_Password_Base_Validation()
|
||||
|
||||
//[Test]
|
||||
//public void ChangePasswordQuestionAndAnswer_Base_Validation()
|
||||
|
||||
//[Test]
|
||||
//public void CreateUser_Base_Validation()
|
||||
[Test]
|
||||
public void Change_Password_Without_AllowManuallyChangingPassword_And_No_Pass_Validation()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
//[Test]
|
||||
//public void GetPassword_Base_Validation()
|
||||
Assert.Throws<NotSupportedException>(() => provider.ChangePassword("test", "", "test"));
|
||||
}
|
||||
|
||||
//[Test]
|
||||
//public void ResetPassword_Base_Validation()
|
||||
[Test]
|
||||
public void Change_Password_With_AllowManuallyChangingPassword_And_Invalid_Creds()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
|
||||
providerMock.Setup(@base => @base.ValidateUser("test", "test")).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.IsFalse(provider.ChangePassword("test", "test", "test"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChangePasswordQuestionAndAnswer_Without_RequiresQuestionAndAnswer()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.Throws<NotSupportedException>(() => provider.ChangePasswordQuestionAndAnswer("test", "test", "test", "test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChangePasswordQuestionAndAnswer_Without_AllowManuallyChangingPassword_And_Invalid_Creds()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
|
||||
providerMock.Setup(@base => @base.AllowManuallyChangingPassword).Returns(false);
|
||||
providerMock.Setup(@base => @base.ValidateUser("test", "test")).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.IsFalse(provider.ChangePasswordQuestionAndAnswer("test", "test", "test", "test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateUser_Not_Whitespace()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() {CallBase = true};
|
||||
var provider = providerMock.Object;
|
||||
|
||||
MembershipCreateStatus status;
|
||||
var result = provider.CreateUser("", "", "test@test.com", "", "", true, "", out status);
|
||||
|
||||
Assert.IsNull(result);
|
||||
Assert.AreEqual(MembershipCreateStatus.InvalidUserName, status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateUser_Invalid_Question()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
MembershipCreateStatus status;
|
||||
var result = provider.CreateUser("test", "test", "test@test.com", "", "", true, "", out status);
|
||||
|
||||
Assert.IsNull(result);
|
||||
Assert.AreEqual(MembershipCreateStatus.InvalidQuestion, status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateUser_Invalid_Answer()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.RequiresQuestionAndAnswer).Returns(true);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
MembershipCreateStatus status;
|
||||
var result = provider.CreateUser("test", "test", "test@test.com", "test", "", true, "", out status);
|
||||
|
||||
Assert.IsNull(result);
|
||||
Assert.AreEqual(MembershipCreateStatus.InvalidAnswer, status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPassword_Without_EnablePasswordRetrieval()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.EnablePasswordRetrieval).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.Throws<ProviderException>(() => provider.GetPassword("test", "test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetPassword_With_Hashed()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.EnablePasswordRetrieval).Returns(true);
|
||||
providerMock.Setup(@base => @base.PasswordFormat).Returns(MembershipPasswordFormat.Hashed);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.Throws<ProviderException>(() => provider.GetPassword("test", "test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResetPassword_Without_EnablePasswordReset()
|
||||
{
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
providerMock.Setup(@base => @base.EnablePasswordReset).Returns(false);
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.Throws<NotSupportedException>(() => provider.ResetPassword("test", "test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Sets_Defaults()
|
||||
{
|
||||
var provider = new TestProvider();
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
var provider = providerMock.Object;
|
||||
provider.Initialize("test", new NameValueCollection());
|
||||
|
||||
Assert.AreEqual("test", provider.Name);
|
||||
@@ -65,7 +282,8 @@ namespace Umbraco.Tests.Membership
|
||||
[Test]
|
||||
public void Throws_Exception_With_Hashed_Password_And_Password_Retrieval()
|
||||
{
|
||||
var provider = new TestProvider();
|
||||
var providerMock = new Mock<MembershipProviderBase>() { CallBase = true };
|
||||
var provider = providerMock.Object;
|
||||
|
||||
Assert.Throws<ProviderException>(() => provider.Initialize("test", new NameValueCollection()
|
||||
{
|
||||
@@ -125,88 +343,5 @@ namespace Umbraco.Tests.Membership
|
||||
Assert.AreEqual(salt, initSalt);
|
||||
}
|
||||
|
||||
private class TestProvider : MembershipProviderBase
|
||||
{
|
||||
public override void UpdateUser(MembershipUser user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool ValidateUser(string username, string password)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool UnlockUser(string userName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(string username, bool userIsOnline)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string GetUserNameByEmail(string email)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool DeleteUser(string username, bool deleteAllRelatedData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override int GetNumberOfUsersOnline()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override string PerformGetPassword(string username, string answer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override string PerformResetPassword(string username, string answer, string generatedPassword)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core;
|
||||
@@ -30,6 +31,15 @@ namespace Umbraco.Web.Security.Providers
|
||||
get { return _memberService ?? (_memberService = ApplicationContext.Current.Services.MemberService); }
|
||||
}
|
||||
|
||||
public MembersMembershipProvider()
|
||||
{
|
||||
}
|
||||
|
||||
internal MembersMembershipProvider(IMemberService memberService)
|
||||
{
|
||||
_memberService = memberService;
|
||||
}
|
||||
|
||||
public string ProviderName
|
||||
{
|
||||
get { return "MembersMembershipProvider"; }
|
||||
@@ -80,7 +90,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
// This is allowed based on the overridden AllowManuallyChangingPassword option.
|
||||
|
||||
// in order to support updating passwords from the umbraco core, we can't validate the old password
|
||||
var m = _memberService.GetByUsername(username);
|
||||
var m = MemberService.GetByUsername(username);
|
||||
if (m == null) return false;
|
||||
|
||||
string salt;
|
||||
@@ -88,8 +98,8 @@ namespace Umbraco.Web.Security.Providers
|
||||
|
||||
m.Password = FormatPasswordForStorage(encodedPassword, salt);
|
||||
m.LastPasswordChangeDate = DateTime.Now;
|
||||
|
||||
_memberService.Save(m);
|
||||
|
||||
MemberService.Save(m);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -113,7 +123,7 @@ namespace Umbraco.Web.Security.Providers
|
||||
}
|
||||
|
||||
member.PasswordQuestion = newPasswordQuestion;
|
||||
member.PasswordAnswer = newPasswordAnswer;
|
||||
member.PasswordAnswer = EncryptString(newPasswordAnswer);
|
||||
|
||||
MemberService.Save(member);
|
||||
|
||||
@@ -158,10 +168,14 @@ namespace Umbraco.Web.Security.Providers
|
||||
string salt;
|
||||
var encodedPassword = EncryptOrHashNewPassword(password, out salt);
|
||||
|
||||
var member = MemberService.CreateMember(email, username, encodedPassword, memberTypeAlias);
|
||||
var member = MemberService.CreateMember(
|
||||
email,
|
||||
username,
|
||||
FormatPasswordForStorage(encodedPassword, salt),
|
||||
memberTypeAlias);
|
||||
|
||||
member.PasswordQuestion = passwordQuestion;
|
||||
member.PasswordAnswer = passwordAnswer;
|
||||
member.PasswordAnswer = EncryptString(passwordAnswer);
|
||||
member.IsApproved = isApproved;
|
||||
member.LastLoginDate = DateTime.Now;
|
||||
member.LastPasswordChangeDate = DateTime.Now;
|
||||
@@ -289,9 +303,9 @@ namespace Umbraco.Web.Security.Providers
|
||||
throw new ProviderException("The supplied user is not found");
|
||||
}
|
||||
|
||||
//TODO: We need to encrypt the answer here to match against the encrypted answer in the database
|
||||
var encAnswer = EncryptString(answer);
|
||||
|
||||
if (RequiresQuestionAndAnswer && m.PasswordAnswer != answer)
|
||||
if (RequiresQuestionAndAnswer && m.PasswordAnswer != encAnswer)
|
||||
{
|
||||
throw new ProviderException("Incorrect password answer");
|
||||
}
|
||||
@@ -301,6 +315,15 @@ namespace Umbraco.Web.Security.Providers
|
||||
return decodedPassword;
|
||||
}
|
||||
|
||||
internal string EncryptString(string str)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(str);
|
||||
var password = new byte[bytes.Length];
|
||||
Buffer.BlockCopy(bytes, 0, password, 0, bytes.Length);
|
||||
var encBytes = EncryptPassword(password, MembershipPasswordCompatibilityMode.Framework40);
|
||||
return Convert.ToBase64String(encBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user.
|
||||
/// </summary>
|
||||
@@ -395,16 +418,16 @@ namespace Umbraco.Web.Security.Providers
|
||||
throw new ProviderException("The member is locked out.");
|
||||
}
|
||||
|
||||
//TODO: We need to encrypt the answer here to match against the encrypted answer in the database
|
||||
var encAnswer = EncryptString(answer);
|
||||
|
||||
if (RequiresQuestionAndAnswer && m.PasswordAnswer != answer)
|
||||
if (RequiresQuestionAndAnswer && m.PasswordAnswer != encAnswer)
|
||||
{
|
||||
throw new ProviderException("Incorrect password answer");
|
||||
}
|
||||
|
||||
string salt;
|
||||
var encodedPassword = EncryptOrHashNewPassword(generatedPassword, out salt);
|
||||
m.Password = encodedPassword;
|
||||
m.Password = FormatPasswordForStorage(encodedPassword, salt);
|
||||
m.LastPasswordChangeDate = DateTime.Now;
|
||||
MemberService.Save(m);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user