ASP.NET 自定义 MembershipProvider和RoleProvider

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

ASP.NET 自定义 MembershipProvider和RoleProvider的相关文章

asp.net自定义错误页面

ASP.NET 提供三种用于在出现错误时捕获和响应错误的主要方法:Page_Error 事件.Application_Error 事件以及应用程序配置文件 (Web.config). 如果您不调用 Server.ClearError 或者捕获 Page_Error 或 Application_Error 事件中的错误,则将根据 Web.config 文件的 <customErrors> 部分中的设置处理错误.在 <customErrors> 部分,可将重定向页指定为默认的错误页 (

ASP.NET自定义404和500错误页面

在ASP.NET网站项目实际上线运行的过程中,有时候在运行环境下会出现400错误或者500错误,这些错误默认的页面都不友好,比较简单单调,其实我们可以自行设置这些错误所对应的页面,让这些错误跳转到我们指定的路径.此文将介绍如何在ASP.NET项目中设置404错误和500错误为例. 首先我们可以到网上下载到一些优美的404错误页面或者500错误页面的HTML模板,或者你也可以自行制作个HTML模板.然后将该页面放入到你的网站项目中,如果你的项目为WebForm项目,则你将需要新建一个Error.A

MongoDB实现ASP.NET 自定义Session

由来     由于HTTP协议是无状态的,客户端与服务器端进行"请求-响应"操作后,建立的连接就释放了,服务器端根本不知道刚才是哪个客户端访问的.但是有些场景是需要知道客户端的状态的,最典型的就是登陆问题,成功登陆后一段时间内就不需要再登陆.为了解决这个问题,服务器端引入了Session技术,它将会话状态保存在服务器端的技术. Session原理     当用户打开浏览器,请求某个网站的时候,服务器接收请求后,就会在内存中为该请求分配一个内存空间,这个内存空间就叫Session.一个S

翻译:ASP.NETMVC自定义错误页面真的简单吗?

如果你在设置asp.net mvc自定义错误页面时遇到问题,这并不止你一个人.惊讶之余你的做法是正确的,没有起到作用的原因是其一部分错误是由asp.net管道处理的,另一部分是由iis直接处理. 通常情况 (我期望是这种情况,在一些其他框架/服务器上) 我们只需要在一个地方配置自定义错误页就可以了,无论怎么哪儿引发的错误.就像这样︰ <customErrors mode="On"> <error code="404" path="404.

(十)ASP.NET自定义用户控件(3)

using HX.DHL.EIP.Services.Def.Localization; using HX.DHL.EIP.Web.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Win

(八)ASP.NET自定义用户控件(1)

http://blog.csdn.net/laodao1/article/details/5897366 ASP.NET自定义控件组件开发 第一章:从一个简单的控件谈起 起始开发ASP.NET自定义控件不是那么的高深,当初我开始学的时候还有点恐惧,但是慢慢就好了.学习控件的开发技术,并不一定说以后要从事控件的开发,而是让我们深入的理解掌握ASP.NET内部的机理.你会发觉,当学习完控件开发技术后,你以后开发网站时有种得心应手的感觉.我不希望一上来就讲控件开始多么多么难啊,我会用一个演化的方法来讲

(九)ASP.NET自定义用户控件(2)

http://www.cnblogs.com/SkySoot/archive/2012/09/04/2670678.html 用户控件 在 .NET 里,可以通过两种方式把自己的控件插入到 Web 窗体框架中: 用户控件:它是一小段页面,可以包括静态 HTML 代码和 Web 服务器控件.用户控件的好处是一旦创建了它,就可以在同一个 Web 应用程序的多个页面重用它.用户控件可以加入自己的属性,事件和方法. 自定义服务器控件:它是被编译的类,它通过编程生成自己的 HTML .服务器控件总是预编译

asp.net 自定义的模板方法接口通用类型

本来想写这个帖子已经很久了,但是公司事情多,做着做着就忘记了.公司因为需要做接口,而且用的还是asp.net的老框架,使用Handler来做,没得办法,自己照着MVC写了一个通过的接口操作模板. 上送json数据,返回的也是json数据.可以像MVC一样自动绑定并可以进行DataAnnotations验证.尽量达到在业务逻辑处理区域不用对上送参数做过多的获取和判断,能一次搞定就一次搞定. 话不多说,上代码!!! BaseClass:用作接口参数的基类.接口参数类型可以继承该类,也可以不继承,或自

asp.net自定义数据库连接类(OLEDB)

类库.cs代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.OleDb; /// <summary> ///Myclass 的摘要说明 /// </summary> /// namespace test { public class superCnn { public OleDbConnection cnn; pri