到目前为止,我已经在我的MVC3应用程序中完成了所有身份验证工作,即通过我的MemberRepository
课程验证成员并创建成员。我现在想通过自定义MembershipProvider
去官方。到目前为止,我只收集到了我真的需要覆盖这个类的ValidateUser
方法,因为我没有使用Login控件,所以我甚至不确定我是否必须这样做。
覆盖GetUser
和CreateUser
等方法会为我的聚会带来未经邀请的类型,例如MembershipUser
,我有一个精心设计的Member
课程。如果我不打算使用任何内置控件或管理工具,如果我不打算使用任何内置控件或管理工具,那么有人可以为我清理我是否真的需要自定义成员资格提供程序,如果我这样做,我是否应该将我的覆盖限制在绝对必要的范围内,这是什么?
答案 0 :(得分:2)
这是我为单元测试编写的。这是最小的可能。
public class MockMembershipProvider : MembershipProvider
{
public IList<MembershipUser> Users { get; private set; }
private string _applicationName;
public override string ApplicationName
{
get
{
return _applicationName;
}
set
{
_applicationName = value;
}
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new NotImplementedException();
}
public override MembershipUser CreateUser(
string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
var user = new MembershipUser(ProviderName, username, username, email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
Users.Add(user);
status = MembershipCreateStatus.Success;
return user;
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
var u = Users.Where(mu => mu.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (u == null) return false;
Users.Remove(u);
return true;
}
public override bool EnablePasswordReset
{
get { return false; }
}
public override bool EnablePasswordRetrieval
{
get { return false; }
}
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)
{
var users = (from u in Users
where u.UserName.Equals(usernameToMatch, StringComparison.OrdinalIgnoreCase)
select u).ToList();
totalRecords = users.Count;
return ToMembershipUserCollection(users);
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
var list = Users.Skip(pageIndex * pageSize).Take(pageSize);
totalRecords = list.Count();
var result = new MembershipUserCollection();
foreach (var u in list)
{
result.Add(u);
}
return result;
}
public override int GetNumberOfUsersOnline()
{
return Users.Count();
}
public override string GetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
return (from u in Users
where u.ProviderUserKey.ToString() == providerUserKey.ToString()
select u).FirstOrDefault();
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
return (from u in Users
where u.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)
select u).FirstOrDefault();
}
public override string GetUserNameByEmail(string email)
{
return (from u in Users
where u.Email.Equals(email, StringComparison.OrdinalIgnoreCase)
select u.UserName).FirstOrDefault();
}
public override int MaxInvalidPasswordAttempts
{
get { return 3; }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { return 1; }
}
public override int MinRequiredPasswordLength
{
get { return 6; }
}
public override int PasswordAttemptWindow
{
get { return 10; }
}
public override MembershipPasswordFormat PasswordFormat
{
get { throw new NotImplementedException(); }
}
public override string PasswordStrengthRegularExpression
{
get { return null; }
}
public override string Name
{
get
{
return ProviderName;
}
}
public string ProviderName { get; set; }
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool RequiresQuestionAndAnswer
{
get { return false; }
}
public override bool RequiresUniqueEmail
{
get { return true; }
}
private MembershipUserCollection ToMembershipUserCollection(IEnumerable<MembershipUser> users)
{
var result = new MembershipUserCollection();
foreach (var u in users)
{
result.Add(u);
}
return result;
}
public override bool UnlockUser(string userName)
{
return true;
}
public override void UpdateUser(MembershipUser user)
{
var oldUser = Users.Where(u => u.UserName.Equals(user.UserName, StringComparison.OrdinalIgnoreCase)).Single();
var index = Users.IndexOf(oldUser);
Users[index] = user;
}
public override bool ValidateUser(string username, string password)
{
throw new NotImplementedException();
}
public MockMembershipProvider()
{
this.ProviderName = "MockMembershipProvider";
Users = new List<MembershipUser>();
}
}
public class FakeMembershipProvider : MockMembershipProvider
{
public FakeMembershipProvider(string name)
{
this.ProviderName = name ?? "MockMembershipProvider";
}
public override MembershipUser CreateUser(
string username,
string password,
string email,
string passwordQuestion,
string passwordAnswer,
bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
status = MembershipCreateStatus.ProviderError;
var user = new MockMembershipUser();
user.Password = password;
user.User = username;
user.UserKey = providerUserKey;
Users.Add(user);
status = MembershipCreateStatus.Success;
return user;
}
}
public class MockMembershipUser : MembershipUser
{
public string Password { get; set; }
public string User { get; set; }
public object UserKey { get; set; }
public override string UserName { get { return User; } }
public override string Comment { get; set; }
public override object ProviderUserKey { get { return UserKey; } }
public override string GetPassword()
{
return Password ?? string.Empty;
}
答案 1 :(得分:1)
您想要将您的网络应用与MembershipRepository
分开吗?
如果是这样,请在custom MembershipProvider中实现所有相同的功能,以便您的应用仅依赖于.NET Membership classes(除了您的web.config)。
如果没有,那就不要打扰了。
答案 2 :(得分:1)
自定义MembershipProvider
如果您正在使用MembershipProvider,则可以“免费”获得一些不错的安全功能:例如,您可以设置web.config以将每个未经身份验证的用户重定向到登录页面。或者,您可以将站点的特定部分设置为仅对具有特定角色的用户可见。如果这些功能对您的项目没有意义,或者您已经以其他方式实现了它们的等效功能,则实现自定义MembershipProvider并没有多大意义。
<强>的SqlMembershipProvider 强>
您可能要考虑的另一种可能性是切换您自己的实现以使用SqlMembershipProvider来处理成员函数。
SqlMembershipProvider为常见任务提供了一个强大的,经过验证的平台,这些任务对于每个项目都需要重新创建:帐户创建,验证,删除,锁定,密码重置,基本角色等。如果您已经完成所有操作你自己没有使用SqlMembershipProvider,实际上没有任何一点只是为了拥有它而创建一个。但是,你应该小心,因为你很可能在自己的实现中做错了。例如,
SqlMembershipProvider已经以易于配置的方式解决了所有这些问题。您可能希望拥有自己的成员资格接口,并且DTO只需将此默认MembershipProvider包装起来,这样您就不必担心这些不同的问题。这样,您的大多数代码都不必与这些“未经邀请的类型”进行交互,但您仍然可以在后端获得广泛使用且经过验证的安全框架的优势。