要创建自定义成员资格提供程序,我按照以下说明操作:
How do I create a custom membership provider for ASP.NET MVC 2?
这些:
http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx
到目前为止,我已设法实现自定义成员资格提供程序,该部分工作正常。 RoleManager仍需要一些修改......
项目结构:
alt text http://img691.imageshack.us/img691/3875/21593096.gif
SAMembershipProvider.cs:
public class SAMembershipProvider : MembershipProvider
{
#region - Properties -
private int NewPasswordLength { get; set; }
private string ConnectionString { get; set; }
public bool enablePasswordReset { get; set; }
public bool enablePasswordRetrieval { get; set; }
public bool requiresQuestionAndAnswer { get; set; }
public bool requiresUniqueEmail { get; set; }
public int maxInvalidPasswordAttempts { get; set; }
public int passwordAttemptWindow { get; set; }
public MembershipPasswordFormat passwordFormat { get; set; }
public int minRequiredNonAlphanumericCharacters { get; set; }
public int minRequiredPasswordLength { get; set; }
public string passwordStrengthRegularExpression { get; set; }
public override string ApplicationName { get; set; }
public override bool EnablePasswordRetrieval
{
get { return enablePasswordRetrieval; }
}
public override bool EnablePasswordReset
{
get { return enablePasswordReset; }
}
public override bool RequiresQuestionAndAnswer
{
get { return requiresQuestionAndAnswer; }
}
public override int MaxInvalidPasswordAttempts
{
get { return maxInvalidPasswordAttempts; }
}
public override int PasswordAttemptWindow
{
get { return passwordAttemptWindow; }
}
public override bool RequiresUniqueEmail
{
get { return requiresUniqueEmail; }
}
public override MembershipPasswordFormat PasswordFormat
{
get { return passwordFormat; }
}
public override int MinRequiredPasswordLength
{
get { return minRequiredPasswordLength; }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { return minRequiredNonAlphanumericCharacters; }
}
public override string PasswordStrengthRegularExpression
{
get { return passwordStrengthRegularExpression; }
}
#endregion
#region - Methods -
public override void Initialize(string name, NameValueCollection config)
{
throw new NotImplementedException();
}
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)
{
throw new NotImplementedException();
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
throw new NotImplementedException();
}
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)
{
throw new NotImplementedException();
}
public override int GetNumberOfUsersOnline()
{
throw new NotImplementedException();
}
public override string GetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
throw new NotImplementedException();
}
public override string GetUserNameByEmail(string email)
{
throw new NotImplementedException();
}
protected override void OnValidatingPassword(ValidatePasswordEventArgs e)
{
base.OnValidatingPassword(e);
}
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool UnlockUser(string userName)
{
throw new NotImplementedException();
}
public override void UpdateUser(MembershipUser user)
{
throw new NotImplementedException();
}
public override bool ValidateUser(string username, string password)
{
AccountRepository accountRepository = new AccountRepository();
var user = accountRepository.GetUser(username);
if (string.IsNullOrEmpty(password.Trim())) return false;
if (user == null) return false;
//string hash = EncryptPassword(password);
var email = user.Email;
var pass = user.Password;
if (user == null) return false;
if (pass == password)
{
//User = user;
return true;
}
return false;
}
#endregion
protected string EncryptPassword(string password)
{
//we use codepage 1252 because that is what sql server uses
byte[] pwdBytes = Encoding.GetEncoding(1252).GetBytes(password);
byte[] hashBytes = System.Security.Cryptography.MD5.Create().ComputeHash(pwdBytes);
return Encoding.GetEncoding(1252).GetString(hashBytes);
}
}
SARoleProvider.cs
public class SARoleProvider : RoleProvider
{
AccountRepository accountRepository = new AccountRepository();
public override bool IsUserInRole(string username, string roleName)
{
return true;
}
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
public override string[] GetRolesForUser(string username)
{
int rolesCount = 0;
IQueryable<RoleViewModel> rolesNames;
try
{
// get roles for this user from DB...
rolesNames = accountRepository.GetRolesForUser(username);
rolesCount = rolesNames.Count();
}
catch (Exception ex)
{
throw ex;
}
string[] roles = new string[rolesCount];
int counter = 0;
foreach (var item in rolesNames)
{
roles[counter] = item.RoleName.ToString();
counter++;
}
return roles;
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
}
AccountRepository.cs
public class RoleViewModel
{
public string RoleName { get; set; }
}
public class AccountRepository
{
private DB db = new DB();
public User GetUser(string email)
{
return db.Users.SingleOrDefault(d => d.Email == email);
}
public IQueryable<RoleViewModel> GetRolesForUser(string email)
{
var result = (
from role in db.Roles
join user in db.Users on role.RoleID equals user.RoleID
where user.Email == email
select new RoleViewModel
{
RoleName = role.Name
});
return result;
}
}
webconfig
<membership defaultProvider="SAMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear/>
<add
name="SAMembershipProvider"
type="SA_Contacts.Membership.SAMembershipProvider, SA_Contacts"
connectionStringName ="ShinyAntConnectionString"
/>
</providers>
</membership>
<roleManager defaultProvider="SARoleProvider" enabled="true" cacheRolesInCookie="true">
<providers>
<clear/>
<add
name="SARoleProvider"
type="SA_Contacts.Membership.SARoleProvider"
connectionStringName ="ShinyAntConnectionString"
/>
</providers>
</roleManager>
AccountController.cs:
public class AccountController : Controller
{
SAMembershipProvider provider = new SAMembershipProvider();
AccountRepository accountRepository = new AccountRepository();
public AccountController()
{
}
public ActionResult LogOn()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(string userName, string password, string returnUrl)
{
if (!ValidateLogOn(userName, password))
{
return View();
}
var user = accountRepository.GetUser(userName);
var userFullName = user.FirstName + " " + user.LastName;
FormsAuthentication.SetAuthCookie(userFullName, false);
if (!String.IsNullOrEmpty(returnUrl) && returnUrl != "/")
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
private bool ValidateLogOn(string userName, string password)
{
if (String.IsNullOrEmpty(userName))
{
ModelState.AddModelError("username", "You must specify a username.");
}
if (String.IsNullOrEmpty(password))
{
ModelState.AddModelError("password", "You must specify a password.");
}
if (!provider.ValidateUser(userName, password))
{
ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
}
return ModelState.IsValid;
}
}
在一些测试控制器中,我有以下内容:
[Authorize]
public class ContactsController : Controller
{
SAMembershipProvider saMembershipProvider = new SAMembershipProvider();
SARoleProvider saRoleProvider = new SARoleProvider();
//
// GET: /Contact/
public ActionResult Index()
{
string[] roleNames = Roles.GetRolesForUser("ilija@ilija.com");
// Outputs admin
ViewData["r1"] = roleNames[0].ToString();
// Outputs True
// I'm not even sure if this method is the same as the one below
ViewData["r2"] = Roles.IsUserInRole("ilija@ilija.com", roleNames[0].ToString());
// Outputs True
ViewData["r3"] = saRoleProvider.IsUserInRole("ilija@ilija.com", "admin");
return View();
}
如果我使用属性[Authorize]
,那么一切正常,但如果我使用[Authorize(Roles="admin")]
,那么用户总是被拒绝,就像他不在角色一样。
知道这里可能出现什么问题?
提前致谢,
ILE
答案 0 :(得分:1)
我发现这与[授权]属性的角色和用户参数有关:
根据自定义Authorize属性中的代码,它看起来像名称可能区分大小写。你试过了吗?
[Authorize(Roles="Admin")]
您也可以尝试使用该文章中的自定义代码,这样您就可以远离使用字符串了。
答案 1 :(得分:1)
我怀疑它正试图调用你尚未在SARoleProvider中实现的方法之一。我先看一下RoleExists方法。在SARoleProvider中的每个方法上设置一个断点,以查看正在调用哪个方法。然后你就会知道你需要使用哪种方法。