using ASPNET.StarterKit.BusinessLogicLayer; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Configuration.Provider; using System.Linq; using System.Runtime.Caching; using System.Security.Cryptography; using System.Text; using System.Web; using System.Web.Configuration; using System.Web.Security; namespace ASPNET.StarterKit.BusinessLogicLayer { /// /// Summary description for TimeTrackerMembershipProvider /// public class TimeTrackerMembershipProvider : MembershipProvider { #region Properties private bool pEnablePasswordRetrieval; public int newPasswordLength { get; set; } public override string ApplicationName { get; set; } private bool pEnablePasswordReset; public override bool EnablePasswordReset { get { return pEnablePasswordReset; } } public override bool EnablePasswordRetrieval { get { return pEnablePasswordRetrieval; } } private int pMaxInvalidPasswordAttempts; public override int MaxInvalidPasswordAttempts { get { return pMaxInvalidPasswordAttempts; } } private int pMinRequiredNonAlphanumericCharacters; public override int MinRequiredNonAlphanumericCharacters { get { return pMinRequiredNonAlphanumericCharacters; } } private int pMinRequiredPasswordLength; public override int MinRequiredPasswordLength { get { return pMinRequiredPasswordLength; } } private int pPasswordAttemptWindow; public override int PasswordAttemptWindow { get { return pPasswordAttemptWindow; } } private MembershipPasswordFormat pPasswordFormat; public override MembershipPasswordFormat PasswordFormat { get { return pPasswordFormat; } } private string pPasswordStrengthRegularExpression; public override string PasswordStrengthRegularExpression { get { return pPasswordStrengthRegularExpression; } } private bool pRequiresQuestionAndAnswer; public override bool RequiresQuestionAndAnswer { get { return pRequiresQuestionAndAnswer; } } private bool pRequiresUniqueEmail; private MachineKeySection machineKey; public override bool RequiresUniqueEmail { get { return pRequiresUniqueEmail; } } private string pPasswordSalt; private string PasswordSalt { get { return pPasswordSalt; } } public bool WriteExceptionsToEventLog { get; set; } #endregion #region init //public TimeTrackerMembershipProvider() : base() //{ // string sectionName = DefaultValues.GetProviderName(); // NameValueCollection section = (NameValueCollection) ConfigurationManager.GetSection("TimeTrackerMembershipProvider"); // this.Initialize("TimeTrackerMembershipProvider", section); //} public override void Initialize(string name, NameValueCollection config) { // // Initialize values from web.config. // if (config == null) throw new ArgumentNullException("config"); if (name == null || name.Length == 0) name = "TimeTrackerMembershipProvider"; if (String.IsNullOrEmpty(config["description"])) { config.Remove("description"); config.Add("description", "Membership provider"); } // Initialize the abstract base class. base.Initialize(name, config); ObjectCache cache = MemoryCache.Default; this.ApplicationName = cache["ApplicationName"] as string; // GetConfigValue(config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath); pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5")); pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10")); pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config["minRequiredNonAlphanumericCharacters"], "1")); pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7")); pPasswordStrengthRegularExpression = Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], "")); pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true")); pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRetrieval"], "true")); pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "false")); pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "true")); WriteExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config["writeExceptionsToEventLog"], "true")); string temp_format = config["passwordFormat"]; if (temp_format == null) { temp_format = "Hashed"; } switch (temp_format) { case "Hashed": pPasswordFormat = MembershipPasswordFormat.Hashed; break; case "Encrypted": pPasswordFormat = MembershipPasswordFormat.Encrypted; break; case "Clear": pPasswordFormat = MembershipPasswordFormat.Clear; break; default: throw new ProviderException("Password format not supported."); } // Get encryption and decryption key information from the configuration. Configuration cfg = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath); machineKey = (MachineKeySection) cfg.GetSection("system.web/machineKey"); if (machineKey.ValidationKey.Contains("AutoGenerate")) if (PasswordFormat != MembershipPasswordFormat.Clear) throw new ProviderException("Hashed or Encrypted passwords " + "are not supported with auto-generated keys."); this.pPasswordSalt = machineKey.ValidationKey; } private string GetConfigValue(string configValue, string defaultValue) { if (String.IsNullOrEmpty(configValue)) return defaultValue; return configValue; } #endregion #region password methods public override bool ChangePassword(string username, string oldPassword, string newPassword) { if (!ValidateUser(username, oldPassword)) 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."); MembershipAppUser u = MembershipAppUser.GetUser(username, true); if (u != null) return (MembershipAppUser.ChangePassword(username, EncodePassword(newPassword), u.PasswordAnswer)); else return false; } public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) { if (!ValidateUser(username, password)) return false; MembershipAppUser u = MembershipAppUser.GetUser(username, false); return (MembershipAppUser.ChangePasswordQuestionAndAnswer(username, newPasswordQuestion, EncodePassword(newPasswordAnswer))); } private bool CheckPassword(string salt,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; } if (pass1 == pass2) { return true; } return false; } #endregion public MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status, string firstName, string lastName, string title, int securityLevel, string creditdept, decimal rate) { ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, password, true); OnValidatingPassword(args); if (args.Cancel) { status = MembershipCreateStatus.InvalidPassword; return null; } if (RequiresUniqueEmail && GetUserNameByEmail(email) != "") { status = MembershipCreateStatus.DuplicateEmail; return null; } MembershipUser u = GetUser(username, false); if (u == null) { DateTime createDate = DateTime.Now; if (providerUserKey == null) { providerUserKey = Guid.NewGuid(); } else { if (!(providerUserKey is Guid)) { status = MembershipCreateStatus.InvalidProviderUserKey; return null; } } bool added = MembershipAppUser.CreateUser(providerUserKey, username, EncodePassword(password), email, passwordQuestion, EncodePassword(passwordAnswer), isApproved, "", createDate, createDate, createDate, ApplicationName, false, createDate, 0, createDate, 0, createDate, firstName, lastName, title, securityLevel, PasswordSalt, (int) this.PasswordFormat, rate, creditdept,false); if (added) { status = MembershipCreateStatus.Success; } else { status = MembershipCreateStatus.UserRejected; } return GetUser(username, false); } else { status = MembershipCreateStatus.DuplicateUserName; } return null; } public override bool DeleteUser(string username, bool deleteAllRelatedData) { return (MembershipAppUser.Delete(username, deleteAllRelatedData)); } public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new NotImplementedException(); } public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new NotImplementedException(); } public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) { totalRecords = 0; MembershipUserCollection c = new MembershipUserCollection(); List users = MembershipAppUser.GetAllUsers(pageSize, pageIndex); foreach (MembershipAppUser u in users) { c.Add(u); totalRecords++; } return c; } public List GetAllUserForEdit() { return MembershipAppUser.GetAllUsers(99999999, 0); } public override int GetNumberOfUsersOnline() { throw new NotImplementedException(); } 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."); } MembershipAppUser u = MembershipAppUser.GetUser(username, false); string password = u.Password; if (RequiresQuestionAndAnswer && !CheckPassword(u.PasswordSalt,password, answer)) { UpdateFailureCount(username, "passwordAnswer"); throw new MembershipPasswordException("Incorrect password answer."); } if (PasswordFormat == MembershipPasswordFormat.Encrypted) { password = UnEncodePassword(password); } return password; } private void UpdateFailureCount(string username, string type) { MembershipAppUser.UpdateFailureCount(username, type); } public override MembershipUser GetUser(string username, bool userIsOnline) { return (MembershipAppUser.GetUser(username, userIsOnline)); } public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { return (MembershipAppUser.GetUser(providerUserKey, userIsOnline)); } public override string GetUserNameByEmail(string email) { string username = MembershipAppUser.GetUserByEmail(email); return username; } public override string ResetPassword(string username, string answer) { if (!EnablePasswordReset) { throw new NotSupportedException("Password reset is not enabled."); } if (answer == null && RequiresQuestionAndAnswer) { UpdateFailureCount(username, "passwordAnswer"); throw new ProviderException("Password answer required for password reset."); } string newPassword = System.Web.Security.Membership.GeneratePassword(newPasswordLength, MinRequiredNonAlphanumericCharacters); ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, true); OnValidatingPassword(args); if (args.Cancel) if (args.FailureInformation != null) throw args.FailureInformation; else throw new MembershipPasswordException("Reset password canceled due to password validation failure."); MembershipAppUser u = MembershipAppUser.GetUser(username, false); string passwordAnswer = ""; if (u != null) { if (u.IsLockedOut) throw new MembershipPasswordException("The supplied user is locked out."); else passwordAnswer = u.PasswordAnswer; } else { throw new MembershipPasswordException("The supplied user name is not found."); } if (RequiresQuestionAndAnswer && !CheckPassword(u.PasswordSalt,answer, passwordAnswer)) { UpdateFailureCount(username, "passwordAnswer"); throw new MembershipPasswordException("Incorrect password answer."); } if (MembershipAppUser.ResetPassword(EncodePassword(newPassword))) return newPassword; return null; } public override bool UnlockUser(string userName) { return (MembershipAppUser.UnlockUser(userName)); } public override void UpdateUser(MembershipUser user) { MembershipAppUser u = user as MembershipAppUser; int returncode = u.Save(); if (returncode == 1) throw new MembershipPasswordException("User not found"); if (returncode == 7) throw new MembershipPasswordException("Email address must be unique."); if (returncode == -1) throw new MembershipPasswordException("Unknown error. Update rolled back"); } public void EditUser( int SecurityLevel, string FirstName, string LastName, string Title, string CreditDepartment, decimal rate, bool IsLockedOut, string UserName) { if (string.IsNullOrEmpty(UserName)) throw (new ArgumentOutOfRangeException("UserName")); AppUser u=AppUser.GetUserByUserName(UserName); u.FirstName = FirstName; u.LastName = LastName; u.Rate = rate; u.Title = Title; u.CreditDepartment = CreditDepartment; u.SecurityLevel = SecurityLevel; if (! u.Save(IsLockedOut)) throw new MembershipPasswordException("User Update Failed"); } public override bool ValidateUser(string username, string password) { MembershipAppUser u = MembershipAppUser.GetUser(username, false); if (u == null) return false; string Userpassword = this.EncodePassword(password); if (Userpassword == u.Password) { if (u.IsLockedOut) return false; return true; } return false; } #region Utilities private 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 = HexToByte(PasswordSalt); encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); break; default: throw new ProviderException("Unsupported password format."); } return encodedPassword; } // // UnEncodePassword // Decrypts or leaves the password clear based on the PasswordFormat. // private 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; } // // HexToByte // Converts a hexadecimal string to a byte array. Used to convert encryption // key values from the configuration. // private byte[] HexToByte(string hexString) { byte[] returnBytes = new byte[hexString.Length / 2]; for (int i = 0; i < returnBytes.Length; i++) returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return returnBytes; } public bool RegisterUser(string UserName, string pwd, string question, string answer, bool isApproved, DateTime CreateDate, Guid UserId) { string pwdEnc = this.EncodePassword(pwd); string ansEnc = this.EncodePassword(answer); return (MembershipAppUser.RegisterUser(UserName, pwdEnc, question, ansEnc, isApproved, CreateDate, UserId, this.PasswordSalt, (int) this.PasswordFormat)); } public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { // Users u = new Users(DefaultValues.GetProviderName(), username, (object) Guid.NewGuid(), email, passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status return this.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status, "", "", "", 0, "", (decimal)0); } public List GetMangers() { return MembershipAppUser.GetAllUsersBySecurityLevel(DefaultValues.GetManagerSecurityLevel()); } #endregion } }