Code First Membership Provider before Migration
This commit is contained in:
@@ -0,0 +1,550 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using MileageTraker.Web.Context;
|
||||
using MileageTraker.Web.Models;
|
||||
|
||||
namespace MileageTraker.Web.Membership
|
||||
{
|
||||
public class CodeFirstMembershipProvider : MembershipProvider
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private const int TokenSizeInBytes = 16;
|
||||
|
||||
public override string ApplicationName
|
||||
{
|
||||
get { return GetType().Assembly.GetName().Name; }
|
||||
set { ApplicationName = GetType().Assembly.GetName().Name; }
|
||||
}
|
||||
|
||||
public override int MaxInvalidPasswordAttempts
|
||||
{
|
||||
get { return 5; }
|
||||
}
|
||||
|
||||
public override int MinRequiredNonAlphanumericCharacters
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override int MinRequiredPasswordLength
|
||||
{
|
||||
get { return 6; }
|
||||
}
|
||||
|
||||
public override int PasswordAttemptWindow
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override MembershipPasswordFormat PasswordFormat
|
||||
{
|
||||
get { return MembershipPasswordFormat.Hashed; }
|
||||
}
|
||||
|
||||
public override string PasswordStrengthRegularExpression
|
||||
{
|
||||
get { return String.Empty; }
|
||||
}
|
||||
|
||||
public override bool RequiresUniqueEmail
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
|
||||
string passwordAnswer, bool isApproved, object providerUserKey,
|
||||
out MembershipCreateStatus status)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
status = MembershipCreateStatus.InvalidUserName;
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
status = MembershipCreateStatus.InvalidPassword;
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(email))
|
||||
{
|
||||
status = MembershipCreateStatus.InvalidEmail;
|
||||
return null;
|
||||
}
|
||||
|
||||
var hashedPassword = Crypto.HashPassword(password);
|
||||
if (hashedPassword.Length > 128)
|
||||
{
|
||||
status = MembershipCreateStatus.InvalidPassword;
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
if (context.Users.Any(usr => usr.Username == username))
|
||||
{
|
||||
status = MembershipCreateStatus.DuplicateUserName;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (context.Users.Any(usr => usr.Email == email))
|
||||
{
|
||||
status = MembershipCreateStatus.DuplicateEmail;
|
||||
return null;
|
||||
}
|
||||
|
||||
var newUser = new User
|
||||
{
|
||||
UserId = Guid.NewGuid(),
|
||||
Username = username,
|
||||
Password = hashedPassword,
|
||||
IsApproved = isApproved,
|
||||
Email = email,
|
||||
CreateDate = DateTime.UtcNow,
|
||||
LastPasswordChangedDate = DateTime.UtcNow,
|
||||
PasswordFailuresSinceLastSuccess = 0,
|
||||
LastLoginDate = DateTime.UtcNow,
|
||||
LastActivityDate = DateTime.UtcNow,
|
||||
LastLockoutDate = DateTime.UtcNow,
|
||||
IsLockedOut = false,
|
||||
LastPasswordFailureDate = DateTime.UtcNow
|
||||
};
|
||||
|
||||
context.Users.Add(newUser);
|
||||
context.SaveChanges();
|
||||
status = MembershipCreateStatus.Success;
|
||||
return new MembershipUser(System.Web.Security.Membership.Provider.Name, newUser.Username, newUser.UserId,
|
||||
newUser.Email, null, null,
|
||||
newUser.IsApproved, newUser.IsLockedOut, newUser.CreateDate.Value,
|
||||
newUser.LastLoginDate.Value, newUser.LastActivityDate.Value,
|
||||
newUser.LastPasswordChangedDate.Value, newUser.LastLockoutDate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public string CreateUserAndAccount(string userName, string password, bool requireConfirmation,
|
||||
IDictionary<string, object> values)
|
||||
{
|
||||
return CreateAccount(userName, password, requireConfirmation);
|
||||
}
|
||||
|
||||
public override bool ValidateUser(string username, string password)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user = context.Users.FirstOrDefault(usr => usr.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!user.IsApproved)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (user.IsLockedOut)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var hashedPassword = user.Password;
|
||||
var verificationSucceeded = (hashedPassword != null && Crypto.VerifyHashedPassword(hashedPassword, password));
|
||||
if (verificationSucceeded)
|
||||
{
|
||||
user.PasswordFailuresSinceLastSuccess = 0;
|
||||
user.LastLoginDate = DateTime.UtcNow;
|
||||
user.LastActivityDate = DateTime.UtcNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
var failures = user.PasswordFailuresSinceLastSuccess;
|
||||
if (failures < MaxInvalidPasswordAttempts)
|
||||
{
|
||||
user.PasswordFailuresSinceLastSuccess += 1;
|
||||
user.LastPasswordFailureDate = DateTime.UtcNow;
|
||||
}
|
||||
else if (failures >= MaxInvalidPasswordAttempts)
|
||||
{
|
||||
user.LastPasswordFailureDate = DateTime.UtcNow;
|
||||
user.LastLockoutDate = DateTime.UtcNow;
|
||||
user.IsLockedOut = true;
|
||||
}
|
||||
}
|
||||
context.SaveChanges();
|
||||
return verificationSucceeded;
|
||||
}
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(string username, bool userIsOnline)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user = context.Users.FirstOrDefault(Usr => Usr.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (userIsOnline)
|
||||
{
|
||||
user.LastActivityDate = DateTime.UtcNow;
|
||||
context.SaveChanges();
|
||||
}
|
||||
|
||||
return new MembershipUser(System.Web.Security.Membership.Provider.Name, user.Username, user.UserId, user.Email,
|
||||
null, null,
|
||||
user.IsApproved, user.IsLockedOut, user.CreateDate.Value, user.LastLoginDate.Value,
|
||||
user.LastActivityDate.Value, user.LastPasswordChangedDate.Value,
|
||||
user.LastLockoutDate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
|
||||
{
|
||||
if (providerUserKey is Guid)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user;
|
||||
user = context.Users.Find(providerUserKey);
|
||||
if (user == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (userIsOnline)
|
||||
{
|
||||
user.LastActivityDate = DateTime.UtcNow;
|
||||
context.SaveChanges();
|
||||
}
|
||||
|
||||
return new MembershipUser(System.Web.Security.Membership.Provider.Name, user.Username, user.UserId, user.Email,
|
||||
null, null,
|
||||
user.IsApproved, user.IsLockedOut, user.CreateDate.Value, user.LastLoginDate.Value,
|
||||
user.LastActivityDate.Value, user.LastPasswordChangedDate.Value,
|
||||
user.LastLockoutDate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ChangePassword(string username, string oldPassword, string newPassword)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(oldPassword))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(newPassword))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user = context.Users.FirstOrDefault(Usr => Usr.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var hashedPassword = user.Password;
|
||||
var verificationSucceeded = (hashedPassword != null && Crypto.VerifyHashedPassword(hashedPassword, oldPassword));
|
||||
if (verificationSucceeded)
|
||||
{
|
||||
user.PasswordFailuresSinceLastSuccess = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var failures = user.PasswordFailuresSinceLastSuccess;
|
||||
if (failures < MaxInvalidPasswordAttempts)
|
||||
{
|
||||
user.PasswordFailuresSinceLastSuccess += 1;
|
||||
user.LastPasswordFailureDate = DateTime.UtcNow;
|
||||
}
|
||||
else if (failures >= MaxInvalidPasswordAttempts)
|
||||
{
|
||||
user.LastPasswordFailureDate = DateTime.UtcNow;
|
||||
user.LastLockoutDate = DateTime.UtcNow;
|
||||
user.IsLockedOut = true;
|
||||
}
|
||||
context.SaveChanges();
|
||||
return false;
|
||||
}
|
||||
var newHashedPassword = Crypto.HashPassword(newPassword);
|
||||
if (newHashedPassword.Length > 128)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
user.Password = newHashedPassword;
|
||||
user.LastPasswordChangedDate = DateTime.UtcNow;
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool UnlockUser(string userName)
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
var user = context.Users.FirstOrDefault(Usr => Usr.Username == userName);
|
||||
if (user != null)
|
||||
{
|
||||
user.IsLockedOut = false;
|
||||
user.PasswordFailuresSinceLastSuccess = 0;
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetNumberOfUsersOnline()
|
||||
{
|
||||
var dateActive =
|
||||
DateTime.UtcNow.Subtract(
|
||||
TimeSpan.FromMinutes(Convert.ToDouble(System.Web.Security.Membership.UserIsOnlineTimeWindow)));
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
return context.Users.Count(usr => usr.LastActivityDate > dateActive);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool DeleteUser(string username, bool deleteAllRelatedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var Context = new MileageTrakerContext())
|
||||
{
|
||||
var user = Context.Users.FirstOrDefault(Usr => Usr.Username == username);
|
||||
if (user != null)
|
||||
{
|
||||
Context.Users.Remove(user);
|
||||
Context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetUserNameByEmail(string email)
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
var user = context.Users.FirstOrDefault(usr => usr.Email == email);
|
||||
if (user != null)
|
||||
{
|
||||
return user.Username;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize,
|
||||
out int totalRecords)
|
||||
{
|
||||
var membershipUsers = new MembershipUserCollection();
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
totalRecords = context.Users.Count(Usr => Usr.Email == emailToMatch);
|
||||
var users =
|
||||
context.Users.Where(usr => usr.Email == emailToMatch)
|
||||
.OrderBy(usrn => usrn.Username)
|
||||
.Skip(pageIndex*pageSize)
|
||||
.Take(pageSize);
|
||||
foreach (var user in users)
|
||||
{
|
||||
membershipUsers.Add(new MembershipUser(System.Web.Security.Membership.Provider.Name, user.Username, user.UserId,
|
||||
user.Email, null, null,
|
||||
user.IsApproved, user.IsLockedOut, user.CreateDate.Value,
|
||||
user.LastLoginDate.Value, user.LastActivityDate.Value,
|
||||
user.LastPasswordChangedDate.Value, user.LastLockoutDate.Value));
|
||||
}
|
||||
}
|
||||
return membershipUsers;
|
||||
}
|
||||
|
||||
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize,
|
||||
out int totalRecords)
|
||||
{
|
||||
var MembershipUsers = new MembershipUserCollection();
|
||||
using (var Context = new MileageTrakerContext())
|
||||
{
|
||||
totalRecords = Context.Users.Where(Usr => Usr.Username == usernameToMatch).Count();
|
||||
var Users =
|
||||
Context.Users.Where(Usr => Usr.Username == usernameToMatch)
|
||||
.OrderBy(Usrn => Usrn.Username)
|
||||
.Skip(pageIndex*pageSize)
|
||||
.Take(pageSize);
|
||||
foreach (var user in Users)
|
||||
{
|
||||
MembershipUsers.Add(new MembershipUser(System.Web.Security.Membership.Provider.Name, user.Username, user.UserId,
|
||||
user.Email, null, null,
|
||||
user.IsApproved, user.IsLockedOut, user.CreateDate.Value,
|
||||
user.LastLoginDate.Value, user.LastActivityDate.Value,
|
||||
user.LastPasswordChangedDate.Value, user.LastLockoutDate.Value));
|
||||
}
|
||||
}
|
||||
return MembershipUsers;
|
||||
}
|
||||
|
||||
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
var MembershipUsers = new MembershipUserCollection();
|
||||
using (var Context = new MileageTrakerContext())
|
||||
{
|
||||
totalRecords = Context.Users.Count();
|
||||
var Users = Context.Users.OrderBy(Usrn => Usrn.Username).Skip(pageIndex*pageSize).Take(pageSize);
|
||||
foreach (var user in Users)
|
||||
{
|
||||
MembershipUsers.Add(new MembershipUser(System.Web.Security.Membership.Provider.Name, user.Username, user.UserId,
|
||||
user.Email, null, null,
|
||||
user.IsApproved, user.IsLockedOut, user.CreateDate.Value,
|
||||
user.LastLoginDate.Value, user.LastActivityDate.Value,
|
||||
user.LastPasswordChangedDate.Value, user.LastLockoutDate.Value));
|
||||
}
|
||||
}
|
||||
return MembershipUsers;
|
||||
}
|
||||
|
||||
public string CreateAccount(string userName, string password, bool requireConfirmationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userName))
|
||||
{
|
||||
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidUserName);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
|
||||
}
|
||||
|
||||
var hashedPassword = Crypto.HashPassword(password);
|
||||
if (hashedPassword.Length > 128)
|
||||
{
|
||||
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
|
||||
}
|
||||
|
||||
using (var Context = new MileageTrakerContext())
|
||||
{
|
||||
if (Context.Users.Where(Usr => Usr.Username == userName).Any())
|
||||
{
|
||||
throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName);
|
||||
}
|
||||
|
||||
var token = string.Empty;
|
||||
if (requireConfirmationToken)
|
||||
{
|
||||
token = GenerateToken();
|
||||
}
|
||||
|
||||
var NewUser = new User
|
||||
{
|
||||
UserId = Guid.NewGuid(),
|
||||
Username = userName,
|
||||
Password = hashedPassword,
|
||||
IsApproved = !requireConfirmationToken,
|
||||
Email = string.Empty,
|
||||
CreateDate = DateTime.UtcNow,
|
||||
LastPasswordChangedDate = DateTime.UtcNow,
|
||||
PasswordFailuresSinceLastSuccess = 0,
|
||||
LastLoginDate = DateTime.UtcNow,
|
||||
LastActivityDate = DateTime.UtcNow,
|
||||
LastLockoutDate = DateTime.UtcNow,
|
||||
IsLockedOut = false,
|
||||
LastPasswordFailureDate = DateTime.UtcNow,
|
||||
ConfirmationToken = token
|
||||
};
|
||||
|
||||
Context.Users.Add(NewUser);
|
||||
Context.SaveChanges();
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GenerateToken()
|
||||
{
|
||||
using (var prng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
return GenerateToken(prng);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GenerateToken(RandomNumberGenerator generator)
|
||||
{
|
||||
var tokenBytes = new byte[TokenSizeInBytes];
|
||||
generator.GetBytes(tokenBytes);
|
||||
return HttpServerUtility.UrlTokenEncode(tokenBytes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Not Supported
|
||||
|
||||
//CodeFirstMembershipProvider does not support password retrieval scenarios.
|
||||
public override bool EnablePasswordRetrieval
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
//CodeFirstMembershipProvider does not support password reset scenarios.
|
||||
public override bool EnablePasswordReset
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
//CodeFirstMembershipProvider does not support question and answer scenarios.
|
||||
public override bool RequiresQuestionAndAnswer
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override string GetPassword(string username, string answer)
|
||||
{
|
||||
throw new NotSupportedException("Consider using methods from WebSecurity module.");
|
||||
}
|
||||
|
||||
public override string ResetPassword(string username, string answer)
|
||||
{
|
||||
throw new NotSupportedException("Consider using methods from WebSecurity module.");
|
||||
}
|
||||
|
||||
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion,
|
||||
string newPasswordAnswer)
|
||||
{
|
||||
throw new NotSupportedException("Consider using methods from WebSecurity module.");
|
||||
}
|
||||
|
||||
//CodeFirstMembershipProvider does not support UpdateUser because this method is useless.
|
||||
public override void UpdateUser(MembershipUser user)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Security;
|
||||
using MileageTraker.Web.Context;
|
||||
using MileageTraker.Web.Models;
|
||||
|
||||
namespace MileageTraker.Web.Membership
|
||||
{
|
||||
public class CodeFirstRoleProvider : RoleProvider
|
||||
{
|
||||
public override string ApplicationName
|
||||
{
|
||||
get { return GetType().Assembly.GetName().Name; }
|
||||
set { ApplicationName = GetType().Assembly.GetName().Name; }
|
||||
}
|
||||
|
||||
public override bool RoleExists(string roleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
Role role = context.Roles.FirstOrDefault(rl => rl.RoleName == roleName);
|
||||
return role != null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUserInRole(string username, string roleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user;
|
||||
user = context.Users.FirstOrDefault(usr => usr.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var role = context.Roles.FirstOrDefault(rl => rl.RoleName == roleName);
|
||||
if (role == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return user.Roles.Contains(role);
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetAllRoles()
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
return context.Roles.Select(rl => rl.RoleName).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetUsersInRole(string roleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
Role role = context.Roles.FirstOrDefault(rl => rl.RoleName == roleName);
|
||||
if (role != null)
|
||||
{
|
||||
return role.Users.Select(usr => usr.Username).ToArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] GetRolesForUser(string username)
|
||||
{
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
User user;
|
||||
user = context.Users.FirstOrDefault(Usr => Usr.Username == username);
|
||||
if (user != null)
|
||||
{
|
||||
return user.Roles.Select(rl => rl.RoleName).ToArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
|
||||
{
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(usernameToMatch))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
return (from rl in context.Roles
|
||||
from usr in rl.Users
|
||||
where rl.RoleName == roleName && usr.Username.Contains(usernameToMatch)
|
||||
select usr.Username).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override void CreateRole(string roleName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
Role role = context.Roles.FirstOrDefault(rl => rl.RoleName == roleName);
|
||||
if (role == null)
|
||||
{
|
||||
var newRole = new Role
|
||||
{
|
||||
RoleId = Guid.NewGuid(),
|
||||
RoleName = roleName
|
||||
};
|
||||
context.Roles.Add(newRole);
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
|
||||
{
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
var role = context.Roles.FirstOrDefault(rl => rl.RoleName == roleName);
|
||||
if (role == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (throwOnPopulatedRole)
|
||||
{
|
||||
if (role.Users.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
role.Users.Clear();
|
||||
}
|
||||
context.Roles.Remove(role);
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
var users = context.Users.Where(usr => usernames.Contains(usr.Username)).ToList();
|
||||
var roles = context.Roles.Where(rl => roleNames.Contains(rl.RoleName)).ToList();
|
||||
foreach (var user in users)
|
||||
{
|
||||
foreach (var role in roles)
|
||||
{
|
||||
if (!user.Roles.Contains(role))
|
||||
{
|
||||
user.Roles.Add(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
foreach (var username in usernames)
|
||||
{
|
||||
var us = username;
|
||||
var user = context.Users.FirstOrDefault(u => u.Username == us);
|
||||
if (user != null)
|
||||
{
|
||||
foreach (var roleName in roleNames)
|
||||
{
|
||||
var rl = roleName;
|
||||
var role = user.Roles.FirstOrDefault(r => r.RoleName == rl);
|
||||
if (role != null)
|
||||
{
|
||||
user.Roles.Remove(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace MileageTraker.Web.Membership
|
||||
{
|
||||
public static class Crypto
|
||||
{
|
||||
private const int TokenSizeInBytes = 16;
|
||||
private const int Pbkdf2Count = 1000;
|
||||
private const int Pbkdf2SubkeyLength = 256/8;
|
||||
private const int SaltSize = 128/8;
|
||||
|
||||
|
||||
public static string GenerateSalt(int byteLength = SaltSize)
|
||||
{
|
||||
var Buff = new byte[byteLength];
|
||||
using (var Prng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
Prng.GetBytes(Buff);
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(Buff);
|
||||
}
|
||||
|
||||
public static string Hash(string input, string algorithm = "sha256")
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
|
||||
return Hash(Encoding.UTF8.GetBytes(input), algorithm);
|
||||
}
|
||||
|
||||
public static string Hash(byte[] input, string algorithm = "sha256")
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
|
||||
using (HashAlgorithm alg = HashAlgorithm.Create(algorithm))
|
||||
{
|
||||
if (alg != null)
|
||||
{
|
||||
byte[] hashData = alg.ComputeHash(input);
|
||||
return BinaryToHex(hashData);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "not supported hash alg", algorithm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string SHA1(string input)
|
||||
{
|
||||
return Hash(input, "sha1");
|
||||
}
|
||||
|
||||
public static string SHA256(string input)
|
||||
{
|
||||
return Hash(input, "sha256");
|
||||
}
|
||||
|
||||
/* =======================
|
||||
* HASHED PASSWORD FORMATS
|
||||
* =======================
|
||||
*
|
||||
* Version 0:
|
||||
* PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations.
|
||||
* (See also: SDL crypto guidelines v5.1, Part III)
|
||||
* Format: { 0x00, salt, subkey }
|
||||
*/
|
||||
|
||||
public static string HashPassword(string password)
|
||||
{
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
|
||||
byte[] salt;
|
||||
byte[] subkey;
|
||||
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, Pbkdf2Count))
|
||||
{
|
||||
salt = deriveBytes.Salt;
|
||||
subkey = deriveBytes.GetBytes(Pbkdf2SubkeyLength);
|
||||
}
|
||||
|
||||
var outputBytes = new byte[1 + SaltSize + Pbkdf2SubkeyLength];
|
||||
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
|
||||
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, Pbkdf2SubkeyLength);
|
||||
return Convert.ToBase64String(outputBytes);
|
||||
}
|
||||
|
||||
// hashedPassword must be of the format of HashWithPassword (salt + Hash(salt+input)
|
||||
public static bool VerifyHashedPassword(string hashedPassword, string password)
|
||||
{
|
||||
if (hashedPassword == null)
|
||||
{
|
||||
throw new ArgumentNullException("hashedPassword");
|
||||
}
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
|
||||
byte[] hashedPasswordBytes = Convert.FromBase64String(hashedPassword);
|
||||
|
||||
// Verify a version 0 (see comment above) password hash.
|
||||
|
||||
if (hashedPasswordBytes.Length != (1 + SaltSize + Pbkdf2SubkeyLength) || hashedPasswordBytes[0] != 0x00)
|
||||
{
|
||||
// Wrong length or version header.
|
||||
return false;
|
||||
}
|
||||
|
||||
var salt = new byte[SaltSize];
|
||||
Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize);
|
||||
var storedSubkey = new byte[Pbkdf2SubkeyLength];
|
||||
Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, Pbkdf2SubkeyLength);
|
||||
|
||||
byte[] generatedSubkey;
|
||||
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, Pbkdf2Count))
|
||||
{
|
||||
generatedSubkey = deriveBytes.GetBytes(Pbkdf2SubkeyLength);
|
||||
}
|
||||
return ByteArraysEqual(storedSubkey, generatedSubkey);
|
||||
}
|
||||
|
||||
internal static string BinaryToHex(byte[] data)
|
||||
{
|
||||
var hex = new char[data.Length*2];
|
||||
|
||||
for (int iter = 0; iter < data.Length; iter++)
|
||||
{
|
||||
var hexChar = ((byte) (data[iter] >> 4));
|
||||
hex[iter*2] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
|
||||
hexChar = ((byte) (data[iter] & 0xF));
|
||||
hex[iter*2 + 1] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
|
||||
}
|
||||
return new string(hex);
|
||||
}
|
||||
|
||||
// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
private static bool ByteArraysEqual(byte[] a, byte[] b)
|
||||
{
|
||||
if (ReferenceEquals(a, b))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a == null || b == null || a.Length != b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool areSame = true;
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
{
|
||||
areSame &= (a[i] == b[i]);
|
||||
}
|
||||
return areSame;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using MileageTraker.Web.Context;
|
||||
|
||||
namespace MileageTraker.Web.Membership
|
||||
{
|
||||
public sealed class WebSecurity
|
||||
{
|
||||
public static HttpContextBase Context
|
||||
{
|
||||
get { return new HttpContextWrapper(HttpContext.Current); }
|
||||
}
|
||||
|
||||
public static HttpRequestBase Request
|
||||
{
|
||||
get { return Context.Request; }
|
||||
}
|
||||
|
||||
public static HttpResponseBase Response
|
||||
{
|
||||
get { return Context.Response; }
|
||||
}
|
||||
|
||||
public static IPrincipal User
|
||||
{
|
||||
get { return Context.User; }
|
||||
}
|
||||
|
||||
public static bool IsAuthenticated
|
||||
{
|
||||
get { return User.Identity.IsAuthenticated; }
|
||||
}
|
||||
|
||||
public static MembershipCreateStatus Register(string username, string password, string email, bool isApproved,
|
||||
string firstName, string lastName)
|
||||
{
|
||||
MembershipCreateStatus createStatus;
|
||||
System.Web.Security.Membership.CreateUser(username, password, email, null, null, isApproved, Guid.NewGuid(),
|
||||
out createStatus);
|
||||
|
||||
if (createStatus == MembershipCreateStatus.Success)
|
||||
{
|
||||
using (var context = new MileageTrakerContext())
|
||||
{
|
||||
var user = context.Users.FirstOrDefault(usr => usr.Username == username);
|
||||
user.FirstName = firstName;
|
||||
user.LastName = lastName;
|
||||
context.SaveChanges();
|
||||
}
|
||||
|
||||
if (isApproved)
|
||||
{
|
||||
FormsAuthentication.SetAuthCookie(username, false);
|
||||
}
|
||||
}
|
||||
|
||||
return createStatus;
|
||||
}
|
||||
|
||||
public static Boolean Login(string username, string password, bool persistCookie = false)
|
||||
{
|
||||
var success = System.Web.Security.Membership.ValidateUser(username, password);
|
||||
if (success)
|
||||
{
|
||||
FormsAuthentication.SetAuthCookie(username, persistCookie);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static void Logout()
|
||||
{
|
||||
FormsAuthentication.SignOut();
|
||||
}
|
||||
|
||||
public static MembershipUser GetUser(string username)
|
||||
{
|
||||
return System.Web.Security.Membership.GetUser(username);
|
||||
}
|
||||
|
||||
public static bool ChangePassword(string userName, string currentPassword, string newPassword)
|
||||
{
|
||||
var success = false;
|
||||
try
|
||||
{
|
||||
var currentUser = System.Web.Security.Membership.GetUser(userName, true);
|
||||
success = currentUser.ChangePassword(currentPassword, newPassword);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static bool DeleteUser(string username)
|
||||
{
|
||||
return System.Web.Security.Membership.DeleteUser(username);
|
||||
}
|
||||
|
||||
public static int GetUserId(string userName)
|
||||
{
|
||||
var user = System.Web.Security.Membership.GetUser(userName);
|
||||
return (int) user.ProviderUserKey;
|
||||
}
|
||||
|
||||
public static string CreateAccount(string userName, string password)
|
||||
{
|
||||
return CreateAccount(userName, password, requireConfirmationToken: false);
|
||||
}
|
||||
|
||||
public static string CreateAccount(string userName, string password, bool requireConfirmationToken = false)
|
||||
{
|
||||
var codeFirstMembership = System.Web.Security.Membership.Provider as CodeFirstMembershipProvider;
|
||||
return codeFirstMembership.CreateAccount(userName, password, requireConfirmationToken);
|
||||
}
|
||||
|
||||
public static string CreateUserAndAccount(string userName, string password)
|
||||
{
|
||||
return CreateUserAndAccount(userName, password, propertyValues: null, requireConfirmationToken: false);
|
||||
}
|
||||
|
||||
public static string CreateUserAndAccount(string userName, string password, bool requireConfirmation)
|
||||
{
|
||||
return CreateUserAndAccount(userName, password, propertyValues: null, requireConfirmationToken: requireConfirmation);
|
||||
}
|
||||
|
||||
public static string CreateUserAndAccount(string userName, string password, IDictionary<string, object> values)
|
||||
{
|
||||
return CreateUserAndAccount(userName, password, propertyValues: values, requireConfirmationToken: false);
|
||||
}
|
||||
|
||||
public static string CreateUserAndAccount(string userName, string password, object propertyValues = null,
|
||||
bool requireConfirmationToken = false)
|
||||
{
|
||||
var codeFirstMembership = System.Web.Security.Membership.Provider as CodeFirstMembershipProvider;
|
||||
|
||||
IDictionary<string, object> values = null;
|
||||
if (propertyValues != null)
|
||||
{
|
||||
values = new RouteValueDictionary(propertyValues);
|
||||
}
|
||||
|
||||
return codeFirstMembership.CreateUserAndAccount(userName, password, requireConfirmationToken, values);
|
||||
}
|
||||
|
||||
public static List<MembershipUser> FindUsersByEmail(string Email, int PageIndex, int PageSize)
|
||||
{
|
||||
int totalRecords;
|
||||
return
|
||||
System.Web.Security.Membership.FindUsersByEmail(Email, PageIndex, PageSize, out totalRecords)
|
||||
.Cast<MembershipUser>()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static List<MembershipUser> FindUsersByName(string Username, int PageIndex, int PageSize)
|
||||
{
|
||||
int totalRecords;
|
||||
return
|
||||
System.Web.Security.Membership.FindUsersByName(Username, PageIndex, PageSize, out totalRecords)
|
||||
.Cast<MembershipUser>()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static List<MembershipUser> GetAllUsers(int PageIndex, int PageSize)
|
||||
{
|
||||
int totalRecords;
|
||||
return
|
||||
System.Web.Security.Membership.GetAllUsers(PageIndex, PageSize, out totalRecords).Cast<MembershipUser>().ToList();
|
||||
}
|
||||
|
||||
public static void InitializeDatabaseConnection(string connectionStringName, string userTableName, string userIdColumn,
|
||||
string userNameColumn, bool autoCreateTables)
|
||||
{
|
||||
}
|
||||
|
||||
public static void InitializeDatabaseConnection(string connectionString, string providerName, string userTableName,
|
||||
string userIdColumn, string userNameColumn, bool autoCreateTables)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user