ASP.NET中默认的MembershipProvider和RoleProvider是Sql Server的,但是默认的提供类有时候不能满足要求,如数据库不是Sql Server,或者想使用自己的数据库表结构等原因不想使用自带的提供类,可以自定义提供类
在web.config中定义forms验证的路径和自定义提供类的名称
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0"/> <authentication mode="Forms"> <forms loginUrl="~/Login.aspx" timeout="60" > </forms> </authentication> <membership defaultProvider="AccessMembershipProvider"> <providers> <clear /> <add name="AccessMembershipProvider" type="WebApplication1.CustomProvider.AccessMembershipProvider" applicationName="/" /> </providers> </membership> <roleManager enabled="true" defaultProvider="InProcRoleProvider" > <providers> <clear/> <add name="InProcRoleProvider" type="WebApplication1.CustomProvider.InProcRoleProvider" applicationName="/"/> </providers> </roleManager> <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/> </system.web> <location path="member"> <system.web> <authorization> <allow roles="member,admin"/> <deny users="*"/> </authorization> </system.web> </location> <location path="admin"> <system.web> <authorization> <allow roles="admin"/> <deny users="*"/> </authorization> </system.web> </location> </configuration>
其中定义了admin目录只能由admin的role成员访问,member目录可以由admin和member成员访问
MembershipProvider:
实现了ValidateUser和几个必要的验证属性(MinRequiredPasswordLength等)就可以使登录控件正常使用,其他注册,密码修改等控件实现对应方法即可
这里我使用了Access作为数据源
先定义Access数据操作对象,连接串是固定的,实际情况应该是根据配置文件读取,传递进
public class DaoAccess { private string conStr; public DaoAccess() { conStr = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Database.mdb"; } private int ExecuteNonQuery(string query) { var con = new OleDbConnection(conStr); int rst = -1; OleDbCommand cmd = new OleDbCommand(query, con); try { con.Open(); rst = cmd.ExecuteNonQuery(); } finally { con.Close(); } return rst; } public bool CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer) { string query = string.Format("insert into UserInfo(Name,[Password],Email,PasswordQuestion,PasswordAnswer) values(‘{0}‘,‘{1}‘,‘{2}‘,‘{3}‘,‘{4}‘)", username, password, email, passwordAnswer, passwordQuestion); return ExecuteNonQuery(query)>0; } public bool ChangePassword(string username, string oldPassword, string newPassword) { string query = string.Format("update UserInfo set [Password]=‘{0}‘ where Name=‘{1}‘ and [Password]=‘{2}‘", newPassword, username, oldPassword); return ExecuteNonQuery(query) > 0; } public UserInfo GetUserByName(string username) { string query = string.Format("select * from UserInfo where Name=‘{0}‘", username); OleDbDataAdapter ada = new OleDbDataAdapter(query, new OleDbConnection(conStr)); DataTable dt = new DataTable(); ada.Fill(dt); var userlist= dt.ConvertToList<UserInfo>(); if (userlist.Count > 0) return userlist[0]; return null; }
然后自定义的AccessMembershipProvider中调用数据访问类来读取和写入access
public class AccessMembershipProvider:MembershipProvider { private string providerName ; private DaoAccess adapter = new DaoAccess(); public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { providerName = name; base.Initialize(name, config); } public override string ApplicationName { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public override bool ChangePassword(string username, string oldPassword, string newPassword) { return adapter.ChangePassword(username, oldPassword, newPassword); } 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) { if (!adapter.CreateUser(username, password, email, passwordAnswer, passwordQuestion)) { status = MembershipCreateStatus.DuplicateUserName; } else { status = MembershipCreateStatus.Success; } var now=DateTime.Now; MembershipUser user = new MembershipUser(providerName, username, "", email, password, "" , true, true, now, now, now, now, now); return user; } public override bool DeleteUser(string username, bool deleteAllRelatedData) { throw new NotImplementedException(); } public override bool EnablePasswordReset { get { throw new NotImplementedException(); } } public override bool EnablePasswordRetrieval { get { 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(string username, bool userIsOnline) { var user= adapter.GetUserByName(username); if (user == null) return null; var now=DateTime.Now; return new MembershipUser(providerName, user.Name, user.UserId, user.Email, user.PasswordQuestion, "", true, false, now, now, now, now, now); } public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { throw new NotImplementedException(); } public override string GetUserNameByEmail(string email) { throw new NotImplementedException(); } public override int MaxInvalidPasswordAttempts { get { return 20; } } public override int MinRequiredNonAlphanumericCharacters { get { return 0; } } public override int MinRequiredPasswordLength { get { return 6; } } //获取在锁定成员资格用户之前允许的最大无效密码或无效密码提示问题答案尝试次数的分钟数。 public override int PasswordAttemptWindow { get { return 20; } } public override MembershipPasswordFormat PasswordFormat { get { return MembershipPasswordFormat.Clear; } } public override string PasswordStrengthRegularExpression { get { throw new NotImplementedException(); } } public override bool RequiresQuestionAndAnswer { get { return true; } } public override bool RequiresUniqueEmail { get { return false; } } 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) { var user= adapter.GetUserByName(username); if (user == null) return false; return user.Password == password; } }
RoleProvider:
实现了IsUserInRole方法,就可以使role的验证功能正常,如果要其他增加删除等功能,实现对应方法即可
public class InProcRoleProvider : RoleProvider { //存放用户权限的字典 Dictionary<string, List<string>> _Users = new Dictionary<string, List<string>>(); //权限的列表 List<string> _Roles = new List<string>(); public override void AddUsersToRoles(string[] usernames, string[] roleNames) { CheckRoles(roleNames); foreach (var username in usernames) { foreach (var roleName in roleNames) AddUserToRole(username, roleName); } } private void CheckRoles(string[] roleNames) { foreach (var newRole in roleNames) { if (!_Roles.Any(item => item == newRole)) throw new Exception(newRole + " 不存在"); } } private void AddUserToRole(string username, string roleName) { if (_Users.ContainsKey(username)) { var roles = _Users[username]; if (roles.Any(name => name == roleName)) return; roles.Add(roleName); } else { _Users.Add(username, new List<string>() { roleName }); } } public override string ApplicationName { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public override void CreateRole(string roleName) { _Roles.Add(roleName); } public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) { _Roles.Remove(roleName); _Users= _Users.Where(item => { return item.Value.Any(v => v == roleName) == false; }) .ToDictionary(item => item.Key,item=>item.Value); return true; } public override string[] FindUsersInRole(string roleName, string usernameToMatch) { throw new NotImplementedException(); } public override string[] GetAllRoles() { throw new NotImplementedException(); } public override string[] GetRolesForUser(string username) { if (_Users.ContainsKey(username)) return _Users[username].ToArray(); return new string[0]; } public override string[] GetUsersInRole(string roleName) { throw new NotImplementedException(); } public override bool IsUserInRole(string username, string roleName) { if (_Users.ContainsKey(username)) { return _Users[username].Any(role=>role==roleName); } return false; } public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) { throw new NotImplementedException(); } public override bool RoleExists(string roleName) { return _Roles.Any(role => role == roleName); } }
为了简化代码,InProcRoleProvider用了内存作为存放用户的role数据
在Global.asax的Application_Start方法中初始化
void Application_Start(object sender, EventArgs e) { if(!Roles.RoleExists("admin")) Roles.CreateRole("admin"); if (!Roles.RoleExists("member")) Roles.CreateRole("member"); }
时间: 2024-10-13 21:24:32