#region namespace using System; using System.Collections.Generic; using System.Text; using System.Web.Security; using System.Configuration; using umbraco.BusinessLogic; using System.Security.Cryptography; using System.Web.Util; using System.Collections.Specialized; using System.Configuration.Provider; using umbraco.cms.businesslogic; using umbraco.cms.businesslogic.member; using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; #endregion namespace umbraco.providers.members { /// /// Custom Membership Provider for Umbraco Members (User authentication for Frontend applications NOT umbraco CMS) /// public class UmbracoMembershipProvider : MembershipProvider { #region Fields private string m_ApplicationName; private bool m_EnablePasswordReset; private bool m_EnablePasswordRetrieval; private int m_MaxInvalidPasswordAttempts; private int m_MinRequiredNonAlphanumericCharacters; private int m_MinRequiredPasswordLength; private int m_PasswordAttemptWindow; private MembershipPasswordFormat m_PasswordFormat; private string m_PasswordStrengthRegularExpression; private bool m_RequiresQuestionAndAnswer; private bool m_RequiresUniqueEmail; private string m_DefaultMemberTypeAlias; private string m_LockPropertyTypeAlias; private string m_FailedPasswordAttemptsPropertyTypeAlias; private string m_ApprovedPropertyTypeAlias; private string m_CommentPropertyTypeAlias; private string m_LastLoginPropertyTypeAlias; private string m_PasswordRetrievalQuestionPropertyTypeAlias; private string m_PasswordRetrievalAnswerPropertyTypeAlias; private string m_providerName = Member.UmbracoMemberProviderName; #endregion #region Properties /// /// The name of the application using the custom membership provider. /// /// /// The name of the application using the custom membership provider. public override string ApplicationName { get { return m_ApplicationName; } set { if (string.IsNullOrEmpty(value)) throw new ProviderException("ApplicationName cannot be empty."); if (value.Length > 0) throw new ProviderException("Provider application name too long."); m_ApplicationName = value; } } /// /// Indicates whether the membership provider is configured to allow users to reset their passwords. /// /// /// true if the membership provider supports password reset; otherwise, false. The default is true. public override bool EnablePasswordReset { get { return m_EnablePasswordReset; } } /// /// Indicates whether the membership provider is configured to allow users to retrieve their passwords. /// /// /// true if the membership provider is configured to support password retrieval; otherwise, false. The default is false. public override bool EnablePasswordRetrieval { get { return m_EnablePasswordRetrieval; } } /// /// Gets the number of invalid password or password-answer attempts allowed before the membership user is locked out. /// /// /// The number of invalid password or password-answer attempts allowed before the membership user is locked out. public override int MaxInvalidPasswordAttempts { get { return m_MaxInvalidPasswordAttempts; } } /// /// Gets the minimum number of special characters that must be present in a valid password. /// /// /// The minimum number of special characters that must be present in a valid password. public override int MinRequiredNonAlphanumericCharacters { get { return m_MinRequiredNonAlphanumericCharacters; } } /// /// Gets the minimum length required for a password. /// /// /// The minimum length required for a password. public override int MinRequiredPasswordLength { get { return m_MinRequiredPasswordLength; } } /// /// Gets the number of minutes in which a maximum number of invalid password or password-answer attempts are allowed before the membership user is locked out. /// /// /// The number of minutes in which a maximum number of invalid password or password-answer attempts are allowed before the membership user is locked out. public override int PasswordAttemptWindow { get { return m_PasswordAttemptWindow; } } /// /// Gets a value indicating the format for storing passwords in the membership data store. /// /// /// One of the values indicating the format for storing passwords in the data store. public override MembershipPasswordFormat PasswordFormat { get { return m_PasswordFormat; } } /// /// Gets the regular expression used to evaluate a password. /// /// /// A regular expression used to evaluate a password. public override string PasswordStrengthRegularExpression { get { return m_PasswordStrengthRegularExpression; } } /// /// Gets a value indicating whether the membership provider is configured to require the user to answer a password question for password reset and retrieval. /// /// /// true if a password answer is required for password reset and retrieval; otherwise, false. The default is true. public override bool RequiresQuestionAndAnswer { get { return m_RequiresQuestionAndAnswer; } } /// /// Gets a value indicating whether the membership provider is configured to require a unique e-mail address for each user name. /// /// /// true if the membership provider requires a unique e-mail address; otherwise, false. The default is true. public override bool RequiresUniqueEmail { get { return m_RequiresUniqueEmail; } } #endregion #region Initialization Method /// /// Initializes the provider. /// /// The friendly name of the provider. /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider. /// The name of the provider is null. /// An attempt is made to call /// on a provider after the provider /// has already been initialized. /// The name of the provider has a length of zero. public override void Initialize(string name, NameValueCollection config) { // Intialize values from web.config if (config == null) throw new ArgumentNullException("config"); if (string.IsNullOrEmpty(name)) name = "UmbracoMembershipProvider"; // Initialize base provider class base.Initialize(name, config); m_providerName = name; this.m_EnablePasswordRetrieval = SecUtility.GetBooleanValue(config, "enablePasswordRetrieval", false); this.m_EnablePasswordReset = SecUtility.GetBooleanValue(config, "enablePasswordReset", false); this.m_RequiresQuestionAndAnswer = SecUtility.GetBooleanValue(config, "requiresQuestionAndAnswer", false); this.m_RequiresUniqueEmail = SecUtility.GetBooleanValue(config, "requiresUniqueEmail", true); this.m_MaxInvalidPasswordAttempts = SecUtility.GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0); this.m_PasswordAttemptWindow = SecUtility.GetIntValue(config, "passwordAttemptWindow", 10, false, 0); this.m_MinRequiredPasswordLength = SecUtility.GetIntValue(config, "minRequiredPasswordLength", 7, true, 0x80); this.m_MinRequiredNonAlphanumericCharacters = SecUtility.GetIntValue(config, "minRequiredNonalphanumericCharacters", 1, true, 0x80); this.m_PasswordStrengthRegularExpression = config["passwordStrengthRegularExpression"]; this.m_ApplicationName = config["applicationName"]; if (string.IsNullOrEmpty(this.m_ApplicationName)) this.m_ApplicationName = SecUtility.GetDefaultAppName(); // make sure password format is clear by default. string str = config["passwordFormat"]; if (str == null) str = "Clear"; switch (str.ToLower()) { case "clear": this.m_PasswordFormat = MembershipPasswordFormat.Clear; break; case "encrypted": this.m_PasswordFormat = MembershipPasswordFormat.Encrypted; break; case "hashed": this.m_PasswordFormat = MembershipPasswordFormat.Hashed; break; default: throw new ProviderException("Provider bad password format"); } if ((this.PasswordFormat == MembershipPasswordFormat.Hashed) && this.EnablePasswordRetrieval) throw new ProviderException("Provider can not retrieve hashed password"); // test for membertype (if not specified, choose the first member type available) if (config["defaultMemberTypeAlias"] != null) m_DefaultMemberTypeAlias = config["defaultMemberTypeAlias"]; else if (MemberType.GetAll.Length == 1) m_DefaultMemberTypeAlias = MemberType.GetAll[0].Alias; else throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultMemberTypeAlias' to the add element in the provider declaration in web.config"); // test for approve status if (config["umbracoApprovePropertyTypeAlias"] != null) { m_ApprovedPropertyTypeAlias = config["umbracoApprovePropertyTypeAlias"]; } // test for lock attempts if (config["umbracoLockPropertyTypeAlias"] != null) { m_LockPropertyTypeAlias = config["umbracoLockPropertyTypeAlias"]; } if (config["umbracoFailedPasswordAttemptsPropertyTypeAlias"] != null) { m_FailedPasswordAttemptsPropertyTypeAlias = config["umbracoFailedPasswordAttemptsPropertyTypeAlias"]; } // comment property if (config["umbracoCommentPropertyTypeAlias"] != null) { m_CommentPropertyTypeAlias = config["umbracoCommentPropertyTypeAlias"]; } // last login date if (config["umbracoLastLoginPropertyTypeAlias"] != null) { m_LastLoginPropertyTypeAlias = config["umbracoLastLoginPropertyTypeAlias"]; } // password retrieval if (config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"] != null) { m_PasswordRetrievalQuestionPropertyTypeAlias = config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"]; } if (config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"] != null) { m_PasswordRetrievalAnswerPropertyTypeAlias = config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"]; } } #endregion #region Methods /// /// Processes a request to update the password for a membership user. /// /// The user to update the password for. /// The current password for the specified user. /// The new password for the specified user. /// /// true if the password was updated successfully; otherwise, false. /// public override bool ChangePassword(string username, string oldPassword, string newPassword) { // in order to support updating passwords from the umbraco core, we can't validate the old password Member m = Member.GetMemberFromLoginNameAndPassword(username, oldPassword); if (m == null) return false; ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, true); OnValidatingPassword(args); if (args.Cancel) { if (args.FailureInformation != null) throw args.FailureInformation; else throw new MembershipPasswordException("Change password canceled due to new password validation failure."); } string encodedPassword = EncodePassword(newPassword); m.ChangePassword(encodedPassword); return (m.Password == encodedPassword) ? true : false; } /// /// Processes a request to update the password question and answer for a membership user. /// /// The user to change the password question and answer for. /// The password for the specified user. /// The new password question for the specified user. /// The new password answer for the specified user. /// /// true if the password question and answer are updated successfully; otherwise, false. /// public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) { if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias) && !String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias)) { if (ValidateUser(username, password)) { Member m = Member.GetMemberFromLoginName(username); if (m != null) { updateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, newPasswordQuestion); updateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, newPasswordAnswer); m.Save(); return true; } else { throw new MembershipPasswordException("The supplied user is not found!"); } } else { throw new MembershipPasswordException("Invalid user/password combo"); } } else { throw new NotSupportedException("Updating the password Question and Answer is not valid if the properties aren't set in the config file"); } } /// /// Adds a new membership user to the data source. /// /// The user name for the new user. /// The password for the new user. /// The e-mail address for the new user. /// The password question for the new user. /// The password answer for the new user /// Whether or not the new user is approved to be validated. /// The unique identifier from the membership data source for the user. /// A enumeration value indicating whether the user was created successfully. /// /// A object populated with the information for the newly created user. /// public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { if (Member.GetMemberFromLoginName(username) != null) status = MembershipCreateStatus.DuplicateUserName; else if (Member.GetMemberFromEmail(email) != null) status = MembershipCreateStatus.DuplicateEmail; else { Member m = Member.MakeNew(username, email, MemberType.GetByAlias(m_DefaultMemberTypeAlias), User.GetUser(0)); m.Password = password; MembershipUser mUser = ConvertToMembershipUser(m); // custom fields if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias)) updateMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion); if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias)) updateMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer); if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias)) updateMemberProperty(m, m_ApprovedPropertyTypeAlias, isApproved); if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias)) { mUser.LastActivityDate = DateTime.Now; updateMemberProperty(m, m_LastLoginPropertyTypeAlias, mUser.LastActivityDate); } // save m.Save(); status = MembershipCreateStatus.Success; return mUser; } return null; } /// /// Removes a user from the membership data source. /// /// The name of the user to delete. /// true to delete data related to the user from the database; false to leave data related to the user in the database. /// /// true if the user was successfully deleted; otherwise, false. /// public override bool DeleteUser(string username, bool deleteAllRelatedData) { Member m = Member.GetMemberFromLoginName(username); if (m == null) return false; else { m.delete(); return true; } } /// /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match. /// /// The e-mail address to search for. /// The index of the page of results to return. pageIndex is zero-based. /// The size of the page of results to return. /// The total number of matched users. /// /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex. /// public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new Exception("The method or operation is not implemented."); } /// /// Gets a collection of membership users where the user name contains the specified user name to match. /// /// The user name to search for. /// The index of the page of results to return. pageIndex is zero-based. /// The size of the page of results to return. /// The total number of matched users. /// /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex. /// public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { int counter = 0; int startIndex = pageSize * pageIndex; int endIndex = startIndex + pageSize - 1; MembershipUserCollection membersList = new MembershipUserCollection(); Member[] memberArray = Member.GetMemberByName(usernameToMatch, false); totalRecords = memberArray.Length; foreach (Member m in memberArray) { if (counter >= startIndex) membersList.Add(ConvertToMembershipUser(m)); if (counter >= endIndex) break; counter++; } return membersList; } /// /// Gets a collection of all the users in the data source in pages of data. /// /// The index of the page of results to return. pageIndex is zero-based. /// The size of the page of results to return. /// The total number of matched users. /// /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex. /// public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) { int counter = 0; int startIndex = pageSize * pageIndex; int endIndex = startIndex + pageSize - 1; MembershipUserCollection membersList = new MembershipUserCollection(); Member[] memberArray = Member.GetAll; totalRecords = memberArray.Length; foreach (Member m in memberArray) { if (counter >= startIndex) membersList.Add(ConvertToMembershipUser(m)); if (counter >= endIndex) break; counter++; } return membersList; } /// /// Gets the number of users currently accessing the application. /// /// /// The number of users currently accessing the application. /// public override int GetNumberOfUsersOnline() { return Member.CachedMembers().Count; } /// /// Gets the password for the specified user name from the data source. /// /// The user to retrieve the password for. /// The password answer for the user. /// /// The password for the specified user name. /// public override string GetPassword(string username, string answer) { if (!EnablePasswordRetrieval) throw new ProviderException("Password Retrieval Not Enabled."); if (PasswordFormat == MembershipPasswordFormat.Hashed) throw new ProviderException("Cannot retrieve Hashed passwords."); Member m = Member.GetMemberFromLoginName(username); if (m != null) { if (RequiresQuestionAndAnswer) { // check if password answer property alias is set if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias)) { // check if user is locked out if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias)) { bool isLockedOut = false; bool.TryParse(getMemberProperty(m, m_LockPropertyTypeAlias, true), out isLockedOut); if (isLockedOut) { throw new MembershipPasswordException("The supplied user is locked out"); } } // match password answer if (getMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, false) != answer) { throw new MembershipPasswordException("Incorrect password answer"); } } else { throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes"); } } } if (m == null) { throw new MembershipPasswordException("The supplied user is not found"); } else { return m.Password; } } /// /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user. /// /// The name of the user to get information for. /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. /// /// A object populated with the specified user's information from the data source. /// public override MembershipUser GetUser(string username, bool userIsOnline) { Member m = Member.GetMemberFromLoginName(username); if (m == null) return null; else return ConvertToMembershipUser(m); } /// /// Gets information from the data source for a user based on the unique identifier for the membership user. Provides an option to update the last-activity date/time stamp for the user. /// /// The unique identifier for the membership user to get information for. /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. /// /// A object populated with the specified user's information from the data source. /// public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { Member m = new Member(Convert.ToInt32(providerUserKey)); if (m == null) return null; else return ConvertToMembershipUser(m); } /// /// Gets the user name associated with the specified e-mail address. /// /// The e-mail address to search for. /// /// The user name associated with the specified e-mail address. If no match is found, return null. /// public override string GetUserNameByEmail(string email) { Member m = Member.GetMemberFromEmail(email); if (m == null) return null; else return m.LoginName; } /// /// Resets a user's password to a new, automatically generated password. /// /// The user to reset the password for. /// The password answer for the specified user (not used with Umbraco). /// The new password for the specified user. public override string ResetPassword(string username, string answer) { if (!EnablePasswordReset) { throw new NotSupportedException("Password reset is not supported"); } Member m = Member.GetMemberFromLoginName(username); if (m == null) throw new MembershipPasswordException("The supplied user is not found"); else { if (RequiresQuestionAndAnswer) { // check if password answer property alias is set if (!String.IsNullOrEmpty(m_PasswordRetrievalAnswerPropertyTypeAlias)) { // check if user is locked out if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias)) { bool isLockedOut = false; bool.TryParse(getMemberProperty(m, m_LockPropertyTypeAlias, true), out isLockedOut); if (isLockedOut) { throw new MembershipPasswordException("The supplied user is locked out"); } } // match password answer if (getMemberProperty(m, m_PasswordRetrievalAnswerPropertyTypeAlias, false) != answer) { throw new MembershipPasswordException("Incorrect password answer"); } } else { throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes"); } } string newPassword = Membership.GeneratePassword(MinRequiredPasswordLength, MinRequiredNonAlphanumericCharacters); m.Password = newPassword; return newPassword; } } /// /// Clears a lock so that the membership user can be validated. /// /// The membership user to clear the lock status for. /// /// true if the membership user was successfully unlocked; otherwise, false. /// public override bool UnlockUser(string userName) { if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias)) { Member m = Member.GetMemberFromLoginName(userName); if (m != null) { updateMemberProperty(m, m_LockPropertyTypeAlias, false); return true; } else { throw new Exception(String.Format("No member with the username '{0}' found", userName)); } } else { throw new ProviderException("To enable lock/unlocking, you need to add a 'bool' property on your membertype and add the alias of the property in the 'umbracoLockPropertyTypeAlias' attribute of the membership element in the web.config."); } } /// /// Updates e-mail and potentially approved status, lock status and comment on a user. /// Note: To automatically support lock, approve and comments you'll need to add references to the membertype properties in the /// 'Member' element in web.config by adding their aliases to the 'umbracoApprovePropertyTypeAlias', 'umbracoLockPropertyTypeAlias' and 'umbracoCommentPropertyTypeAlias' attributes /// /// A object that represents the user to update and the updated information for the user. public override void UpdateUser(MembershipUser user) { Member m = Member.GetMemberFromLoginName(user.UserName); m.Email = user.Email; // if supported, update approve status updateMemberProperty(m, m_ApprovedPropertyTypeAlias, user.IsApproved); // if supported, update lock status updateMemberProperty(m, m_LockPropertyTypeAlias, user.IsLockedOut); // if supported, update comment updateMemberProperty(m, m_CommentPropertyTypeAlias, user.Comment); m.Save(); } private void updateMemberProperty(Member m, string propertyAlias, object propertyValue) { if (!String.IsNullOrEmpty(propertyAlias)) { if (m.getProperty(propertyAlias) != null) { m.getProperty(propertyAlias).Value = propertyValue; } } } private string getMemberProperty(Member m, string propertyAlias, bool isBool) { if (!String.IsNullOrEmpty(propertyAlias)) { if (m.getProperty(propertyAlias) != null && m.getProperty(propertyAlias).Value != null) { if (isBool) { // Umbraco stored true as 1, which means it can be bool.tryParse'd return m.getProperty(propertyAlias).Value.ToString().Replace("1", "true").Replace("0", "false"); } else return m.getProperty(propertyAlias).Value.ToString(); } } return null; } /// /// Verifies that the specified user name and password exist in the data source. /// /// The name of the user to validate. /// The password for the specified user. /// /// true if the specified username and password are valid; otherwise, false. /// public override bool ValidateUser(string username, string password) { Member m = Member.GetMemberFromLoginAndEncodedPassword(username, EncodePassword(password)); if (m != null) { // check for lock status. If locked, then set the member property to null if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias)) { string lockedStatus = getMemberProperty(m, m_LockPropertyTypeAlias, true); if (!String.IsNullOrEmpty(lockedStatus)) { bool isLocked = false; if (bool.TryParse(lockedStatus, out isLocked)) { if (isLocked) { m = null; } } } } // check for approve status. If not approved, then set the member property to null if (!checkApproveStatus(m)) { m = null; } // maybe update login date if (m != null && !String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias)) { updateMemberProperty(m, m_LastLoginPropertyTypeAlias, DateTime.Now); } // maybe reset password attempts if (m != null && !String.IsNullOrEmpty(m_FailedPasswordAttemptsPropertyTypeAlias)) { updateMemberProperty(m, m_FailedPasswordAttemptsPropertyTypeAlias, 0); } // persist data if (m != null) m.Save(); } else if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias) && !String.IsNullOrEmpty(m_FailedPasswordAttemptsPropertyTypeAlias)) { Member updateMemberDataObject = Member.GetMemberFromLoginName(username); // update fail rate if it's approved if (updateMemberDataObject != null && checkApproveStatus(updateMemberDataObject)) { int failedAttempts = 0; int.TryParse(getMemberProperty(updateMemberDataObject, m_FailedPasswordAttemptsPropertyTypeAlias, false), out failedAttempts); failedAttempts = failedAttempts+1; updateMemberProperty(updateMemberDataObject, m_FailedPasswordAttemptsPropertyTypeAlias, failedAttempts); // lock user? if (failedAttempts >= MaxInvalidPasswordAttempts) { updateMemberProperty(updateMemberDataObject, m_LockPropertyTypeAlias, true); } } } return (m != null); } private bool checkApproveStatus(Member m) { bool isApproved = false; if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias)) { if (m != null) { string approveStatus = getMemberProperty(m, m_ApprovedPropertyTypeAlias, true); if (!String.IsNullOrEmpty(approveStatus)) { bool.TryParse(approveStatus, out isApproved); } } } else { // if we don't use approve statuses isApproved = true; } return isApproved; } #endregion #region Helper Methods /// /// Checks the password. /// /// The password. /// The dbPassword. /// internal bool CheckPassword(string password, string dbPassword) { string pass1 = password; string pass2 = dbPassword; switch (PasswordFormat) { case MembershipPasswordFormat.Encrypted: pass2 = UnEncodePassword(dbPassword); break; case MembershipPasswordFormat.Hashed: pass1 = EncodePassword(password); break; default: break; } return (pass1 == pass2) ? true : false; } /// /// Encodes the password. /// /// The password. /// The encoded password. public string EncodePassword(string password) { string encodedPassword = password; switch (PasswordFormat) { case MembershipPasswordFormat.Clear: break; case MembershipPasswordFormat.Encrypted: encodedPassword = Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password))); break; case MembershipPasswordFormat.Hashed: HMACSHA1 hash = new HMACSHA1(); hash.Key = Encoding.Unicode.GetBytes(password); encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); break; default: throw new ProviderException("Unsupported password format."); } return encodedPassword; } /// /// Unencode password. /// /// The encoded password. /// The unencoded password. public string UnEncodePassword(string encodedPassword) { string password = encodedPassword; switch (PasswordFormat) { case MembershipPasswordFormat.Clear: break; case MembershipPasswordFormat.Encrypted: password = Encoding.Unicode.GetString(DecryptPassword(Convert.FromBase64String(password))); break; case MembershipPasswordFormat.Hashed: throw new ProviderException("Cannot unencode a hashed password."); default: throw new ProviderException("Unsupported password format."); } return password; } /// /// Converts to membership user. /// /// The m. /// private MembershipUser ConvertToMembershipUser(Member m) { if (m == null) return null; else { DateTime lastLogin = DateTime.Now; bool isApproved = true; bool isLocked = false; string comment = ""; string passwordQuestion = ""; // last login if (!String.IsNullOrEmpty(m_LastLoginPropertyTypeAlias)) { DateTime.TryParse(getMemberProperty(m, m_LastLoginPropertyTypeAlias, false), out lastLogin); } // approved if (!String.IsNullOrEmpty(m_ApprovedPropertyTypeAlias)) { bool.TryParse(getMemberProperty(m, m_ApprovedPropertyTypeAlias, true), out isApproved); } // locked if (!String.IsNullOrEmpty(m_LockPropertyTypeAlias)) { bool.TryParse(getMemberProperty(m, m_LockPropertyTypeAlias, true), out isLocked); } // comment if (!String.IsNullOrEmpty(m_CommentPropertyTypeAlias)) { comment = getMemberProperty(m, m_CommentPropertyTypeAlias, false); } // password question if (!String.IsNullOrEmpty(m_PasswordRetrievalQuestionPropertyTypeAlias)) { passwordQuestion = getMemberProperty(m, m_PasswordRetrievalQuestionPropertyTypeAlias, false); } return new MembershipUser(m_providerName, m.LoginName, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDateTime, lastLogin, DateTime.Now, DateTime.Now, DateTime.Now); } } #endregion } }