590 lines
22 KiB
C#
590 lines
22 KiB
C#
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>
|
|
/// Summary description for TimeTrackerMembershipProvider
|
|
/// </summary>
|
|
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<MembershipAppUser> users = MembershipAppUser.GetAllUsers(pageSize, pageIndex);
|
|
|
|
foreach (MembershipAppUser u in users)
|
|
{
|
|
|
|
c.Add(u);
|
|
totalRecords++;
|
|
}
|
|
return c;
|
|
}
|
|
public List<MembershipAppUser> 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<MembershipAppUser> GetMangers()
|
|
{
|
|
return MembershipAppUser.GetAllUsersBySecurityLevel(DefaultValues.GetManagerSecurityLevel());
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |