Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region Using
- using System;
- using System.Xml;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Configuration.Provider;
- using System.Web.Security;
- using System.Web.Hosting;
- using System.Web.Management;
- using System.Security.Permissions;
- using System.Web;
- using System.Text;
- using System.Security.Cryptography;
- using System.Diagnostics;
- #endregion
- namespace BlogEngine.Core.Providers
- {
- /// <summary>
- ///
- /// </summary>
- public class XmlMembershipProvider : MembershipProvider
- {
- #region Member variables
- private Dictionary<string, MembershipUser> _Users;
- private string _XmlFileName;
- //variables below are added By Van.
- private string pApplicationName;
- private bool pEnablePasswordReset;
- private bool pEnablePasswordRetrieval;
- private bool pRequiresQuestionAndAnswer;
- private bool pRequiresUniqueEmail;
- private int pMaxInvalidPasswordAttempts;
- private int pPasswordAttemptWindow;
- private MembershipPasswordFormat pPasswordFormat;
- private int pMinRequiredNonAlphanumericCharacters;
- private int pMinRequiredPasswordLength;
- private string pPasswordStrengthRegularExpression;
- private int newPasswordLength = 8;
- private string eventSource = "XmlMembershipProvider";
- private string eventLog = "Application";
- private string exceptionMessage = "An exception occurred. Please check the Event Log.";
- //
- // Used when determining encryption key values.
- //
- private MachineKeySection machineKey;
- //
- // If false, exceptions are thrown to the caller. If true,
- // exceptions are written to the event log.
- //
- private bool pWriteExceptionsToEventLog;
- #endregion
- #region Properties
- // MembershipProvider Properties
- /// <summary>
- ///
- /// </summary>
- public override string ApplicationName
- {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
- /// <summary>
- ///
- /// </summary>
- public override bool EnablePasswordRetrieval
- {
- get { return false; }
- }
- /// <summary>
- ///
- /// </summary>
- public override bool EnablePasswordReset
- {
- get { return false; }
- }
- /// <summary>
- ///
- /// </summary>
- public override int MaxInvalidPasswordAttempts
- {
- get { return 5; }
- }
- /// <summary>
- ///
- /// </summary>
- public override int MinRequiredNonAlphanumericCharacters
- {
- get { return 0; }
- }
- /// <summary>
- ///
- /// </summary>
- public override int MinRequiredPasswordLength
- {
- get { return 8; }
- }
- /// <summary>
- ///
- /// </summary>
- public override int PasswordAttemptWindow
- {
- get { throw new NotSupportedException(); }
- }
- /// <summary>
- /// Password Format
- /// </summary>
- public override MembershipPasswordFormat PasswordFormat
- {
- get { return MembershipPasswordFormat.Hashed; }
- }
- /// <summary>
- ///
- /// </summary>
- public override string PasswordStrengthRegularExpression
- {
- get { throw new NotSupportedException(); }
- }
- /// <summary>
- ///
- /// </summary>
- public override bool RequiresQuestionAndAnswer
- {
- get { return false; }
- }
- /// <summary>
- ///
- /// </summary>
- public override bool RequiresUniqueEmail
- {
- get { return false; }
- }
- #endregion
- #region Supported methods
- /// <summary>
- ///
- /// </summary>
- /// <param name="name"></param>
- /// <param name="config"></param>
- public override void Initialize(string name, NameValueCollection config)
- {
- if (config == null)
- throw new ArgumentNullException("config");
- if (String.IsNullOrEmpty(name))
- name = "XmlMembershipProvider";
- if (string.IsNullOrEmpty(config["description"]))
- {
- config.Remove("description");
- config.Add("description", "XML membership provider");
- }
- base.Initialize(name, config);
- //Init member variables
- InitMemberVariables(config);
- // Initialize _XmlFileName and make sure the path
- // is app-relative
- string path = config["xmlFileName"];
- if (String.IsNullOrEmpty(path))
- path = BlogSettings.Instance.StorageLocation + "Users.xml";
- if (!VirtualPathUtility.IsAppRelative(path))
- throw new ArgumentException
- ("xmlFileName must be app-relative");
- string fullyQualifiedPath = VirtualPathUtility.Combine
- (VirtualPathUtility.AppendTrailingSlash
- (HttpRuntime.AppDomainAppVirtualPath), path);
- _XmlFileName = HostingEnvironment.MapPath(fullyQualifiedPath);
- config.Remove("xmlFileName");
- // Make sure we have permission to read the XML data source and
- // throw an exception if we don't
- FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Write, _XmlFileName);
- permission.Demand();
- // Throw an exception if unrecognized attributes remain
- if (config.Count > 0)
- {
- string attr = config.GetKey(0);
- if (!String.IsNullOrEmpty(attr))
- throw new ProviderException("Unrecognized attribute: " + attr);
- }
- }
- /// <summary>
- /// Returns true if the username and password match an exsisting user.
- /// </summary>
- public override bool ValidateUser(string username, string password)
- {
- if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password))
- return false;
- try
- {
- ReadMembershipDataStore();
- // Validate the user name and password
- MembershipUser user;
- string encodePwd;
- if (_Users.TryGetValue(username, out user))
- {
- if (user.Comment == password) // Case-sensitive
- {
- //user.LastLoginDate = DateTime.Now;
- //UpdateUser(user);
- return true;
- }
- }
- return false;
- }
- catch (Exception)
- {
- return false;
- }
- }
- /// <summary>
- /// Retrieves a user based on his/hers username.
- /// the userIsOnline parameter is ignored.
- /// </summary>
- public override MembershipUser GetUser(string username, bool userIsOnline)
- {
- if (String.IsNullOrEmpty(username))
- return null;
- ReadMembershipDataStore();
- // Retrieve the user from the data source
- MembershipUser user;
- if (_Users.TryGetValue(username, out user))
- return user;
- return null;
- }
- /// <summary>
- /// Retrieves a collection of all the users.
- /// This implementation ignores pageIndex and pageSize,
- /// and it doesn't sort the MembershipUser objects returned.
- /// </summary>
- public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
- {
- ReadMembershipDataStore();
- MembershipUserCollection users = new MembershipUserCollection();
- foreach (KeyValuePair<string, MembershipUser> pair in _Users)
- {
- users.Add(pair.Value);
- }
- totalRecords = users.Count;
- return users;
- }
- /// <summary>
- /// Changes a users password.
- /// </summary>
- public override bool ChangePassword(string username, string oldPassword, string newPassword)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- XmlNodeList nodes = doc.GetElementsByTagName("User");
- foreach (XmlNode node in nodes)
- {
- if (node["UserName"].InnerText.Equals(username, StringComparison.OrdinalIgnoreCase)
- || node["Password"].InnerText.Equals(oldPassword, StringComparison.OrdinalIgnoreCase))
- {
- node["Password"].InnerText = newPassword;
- doc.Save(_XmlFileName);
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Creates a new user store he/she in the XML file
- /// </summary>
- public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- XmlNode xmlUserRoot = doc.CreateElement("User");
- XmlNode xmlUserName = doc.CreateElement("UserName");
- XmlNode xmlPassword = doc.CreateElement("Password");
- XmlNode xmlEmail = doc.CreateElement("Email");
- XmlNode xmlLastLoginTime = doc.CreateElement("LastLoginTime");
- xmlUserName.InnerText = username;
- xmlPassword.InnerText = password;
- xmlEmail.InnerText = email;
- xmlLastLoginTime.InnerText = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- xmlUserRoot.AppendChild(xmlUserName);
- xmlUserRoot.AppendChild(xmlPassword);
- xmlUserRoot.AppendChild(xmlEmail);
- xmlUserRoot.AppendChild(xmlLastLoginTime);
- doc.SelectSingleNode("Users").AppendChild(xmlUserRoot);
- doc.Save(_XmlFileName);
- status = MembershipCreateStatus.Success;
- MembershipUser user = new MembershipUser(Name, username, username, email, passwordQuestion, password, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.MaxValue);
- _Users.Add(username, user);
- return user;
- }
- /// <summary>
- /// Deletes the user from the XML file and
- /// removes him/her from the internal cache.
- /// </summary>
- public override bool DeleteUser(string username, bool deleteAllRelatedData)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- foreach (XmlNode node in doc.GetElementsByTagName("User"))
- {
- if (node.ChildNodes[0].InnerText.Equals(username, StringComparison.OrdinalIgnoreCase))
- {
- doc.SelectSingleNode("Users").RemoveChild(node);
- doc.Save(_XmlFileName);
- _Users.Remove(username);
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Get a user based on the username parameter.
- /// the userIsOnline parameter is ignored.
- /// </summary>
- public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- foreach (XmlNode node in doc.SelectNodes("//User"))
- {
- if (node.ChildNodes[0].InnerText.Equals(providerUserKey.ToString(), StringComparison.OrdinalIgnoreCase))
- {
- string userName = node.ChildNodes[0].InnerText;
- string password = node.ChildNodes[1].InnerText;
- string email = node.ChildNodes[2].InnerText;
- DateTime lastLoginTime = DateTime.Parse(node.ChildNodes[3].InnerText);
- return new MembershipUser(Name, providerUserKey.ToString(), providerUserKey, email, string.Empty, password, true, false, DateTime.Now, lastLoginTime, DateTime.Now, DateTime.Now, DateTime.MaxValue);
- }
- }
- return default(MembershipUser);
- }
- /// <summary>
- /// Retrieves a username based on a matching email.
- /// </summary>
- public override string GetUserNameByEmail(string email)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- foreach (XmlNode node in doc.GetElementsByTagName("User"))
- {
- if (node.ChildNodes[2].InnerText.Equals(email.Trim(), StringComparison.OrdinalIgnoreCase))
- {
- return node.ChildNodes[0].InnerText;
- }
- }
- return null;
- }
- /// <summary>
- /// Updates a user. The username will not be changed.
- /// </summary>
- public override void UpdateUser(MembershipUser user)
- {
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- foreach (XmlNode node in doc.GetElementsByTagName("User"))
- {
- if (node.ChildNodes[0].InnerText.Equals(user.UserName, StringComparison.OrdinalIgnoreCase))
- {
- if (user.Comment.Length > 30)
- {
- node.ChildNodes[1].InnerText = user.Comment;
- }
- node.ChildNodes[2].InnerText = user.Email;
- node.ChildNodes[3].InnerText = user.LastLoginDate.ToString("yyyy-MM-dd HH:mm:ss");
- doc.Save(_XmlFileName);
- _Users[user.UserName] = user;
- }
- }
- }
- #endregion
- #region Helper methods
- /// <summary>
- /// Builds the internal cache of users.
- /// </summary>
- private void ReadMembershipDataStore()
- {
- lock (this)
- {
- if (_Users == null)
- {
- _Users = new Dictionary<string, MembershipUser>(16, StringComparer.InvariantCultureIgnoreCase);
- XmlDocument doc = new XmlDocument();
- doc.Load(_XmlFileName);
- XmlNodeList nodes = doc.GetElementsByTagName("User");
- foreach (XmlNode node in nodes)
- {
- MembershipUser user = new MembershipUser(
- Name, // Provider name
- node["UserName"].InnerText, // Username
- node["UserName"].InnerText, // providerUserKey
- node["Email"].InnerText, // Email
- String.Empty, // passwordQuestion
- node["Password"].InnerText, // Comment
- true, // isApproved
- false, // isLockedOut
- DateTime.Now, // creationDate
- DateTime.Parse(node["LastLoginTime"].InnerText), // lastLoginDate
- DateTime.Now, // lastActivityDate
- DateTime.Now, // lastPasswordChangedDate
- new DateTime(1980, 1, 1) // lastLockoutDate
- );
- _Users.Add(user.UserName, user);
- }
- }
- }
- }
- //
- // A helper function to retrieve config values from the configuration file.
- //
- private static string GetConfigValue(string configValue, string defaultValue) {
- if (String.IsNullOrEmpty(configValue))
- return defaultValue;
- return configValue;
- }
- /// <summary>
- /// Fill our member variables according to the config file
- /// </summary>
- /// <param name="config">config</param>
- private static void InitMemberVariables(NameValueCollection config) {
- pApplicationName = GetConfigValue(config["applicationName"], 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"));
- pWriteExceptionsToEventLog = 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.");
- }
- //
- // WriteToEventLog
- // A helper function that writes exception detail to the event log. Exceptions
- // are written to the event log as a security measure to avoid private database
- // details from being returned to the browser. If a method does not return a status
- // or boolean indicating the action succeeded or failed, a generic exception is also
- // thrown by the caller.
- //
- private void WriteToEventLog(Exception e, string action) {
- EventLog log = new EventLog();
- log.Source = eventSource;
- log.Log = eventLog;
- string message = "An exception occurred communicating with the data source.\n\n";
- message += "Action: " + action + "\n\n";
- message += "Exception: " + e.ToString();
- log.WriteEntry(message);
- }
- //
- // 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;
- }
- #region Encode And Decode
- //
- // DecodePassword
- // Decrypts or leaves the password clear based on the PasswordFormat.
- //
- private string DecodePassword(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 decode a hashed password.");
- default:
- throw new ProviderException("Unsupported password format.");
- }
- return password;
- }
- //
- // EncodePassword
- // Encrypts, Hashes, or leaves the password clear based on the PasswordFormat.
- //
- 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(machineKey.ValidationKey);
- encodedPassword =
- Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
- break;
- default:
- throw new ProviderException("Unsupported password format.");
- }
- return encodedPassword;
- }
- /// <summary>
- /// Encrypts a string using the SHA256 algorithm.
- /// </summary>
- private static string Encrypt(string plainMessage) {
- byte[] data = Encoding.UTF8.GetBytes(plainMessage);
- using (HashAlgorithm sha = new SHA256Managed()) {
- byte[] encryptedBytes = sha.TransformFinalBlock(data, 0, data.Length);
- return Convert.ToBase64String(sha.Hash);
- }
- }
- #endregion
- //
- // CheckPassword
- // Compares password values based on the MembershipPasswordFormat.
- //
- private bool CheckPassword(string password, string dbpassword) {
- string pass1 = password;
- string pass2 = dbpassword;
- switch (PasswordFormat) {
- case MembershipPasswordFormat.Encrypted:
- pass2 = DecodePassword(dbpassword);
- break;
- case MembershipPasswordFormat.Hashed:
- pass1 = EncodePassword(password);
- break;
- default:
- break;
- }
- if (pass1 == pass2) {
- return true;
- }
- return false;
- }
- #endregion
- #region Unsupported methods
- /// <summary>
- ///
- /// </summary>
- /// <param name="username"></param>
- /// <param name="answer"></param>
- /// <returns></returns>
- public override string ResetPassword(string username, string answer)
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="userName"></param>
- /// <returns></returns>
- public override bool UnlockUser(string userName)
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="emailToMatch"></param>
- /// <param name="pageIndex"></param>
- /// <param name="pageSize"></param>
- /// <param name="totalRecords"></param>
- /// <returns></returns>
- public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="usernameToMatch"></param>
- /// <param name="pageIndex"></param>
- /// <param name="pageSize"></param>
- /// <param name="totalRecords"></param>
- /// <returns></returns>
- public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <returns></returns>
- public override int GetNumberOfUsersOnline()
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="username"></param>
- /// <param name="password"></param>
- /// <param name="newPasswordQuestion"></param>
- /// <param name="newPasswordAnswer"></param>
- /// <returns></returns>
- public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
- {
- throw new NotSupportedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="username"></param>
- /// <param name="answer"></param>
- /// <returns></returns>
- public override string GetPassword(string username, string answer)
- {
- throw new NotSupportedException();
- }
- #endregion
- }
- }
Add Comment
Please, Sign In to add comment