自定义MembershipProvider来利用Asp.net 2.0 Login控件的登陆和修改密码模块

ChangePassword 控件ASP.net 参考链接:https://msdn.microsoft.com/zh-cn/library/cc294841.aspx 通过“ChangePassword”控件,用户可以更改自己的密码。用户必须先提供原始密码,然后再创建并确认新密码。如果原始密码正确,则用户密码将更改为新密码。该控件还支持发送关于新密码的电子邮件。“ChangePassword”控件由通过身份验证未通过身份 阅读详情

  转向Asp.net 2.0,如果单单看Asp.net 2.0的例子和SDK,相信你一定对系统自带的Login控件有比较深刻的印象。Asp.Net 2.0的Login控件不用你写一行检测用户输入是否合法的程序代码及相关查询数据库的SQL脚本,只需把相应的控件拖到Web表单中,即可完成用户登陆,创建用户,用户角色管理,修改密码用户详细情况,取回密码等功能模块。
  Login控件看上去近乎完美,而我们现在手头正好来了一个项目要求采用Asp.net 2.0开发,而该项目也要求有登陆,用户管理,权限管理,修改密码等功能,相信绝大多数人都会考虑使用Login控件来快速搞定这些要求。于是乎,大家拿出以前的教学例子,试着分析较深一层的代码,看看该在哪里对Login控件修改一番,让它满足手头项目已设计好的数据库表结构。结果发现,除了aspx文件里面可以对Login控件的外观,提示文字可以自定义外,cs文件中愣是找不到一行代码,然后继续翻MSDN和Google,终于知道,要在自己的项目中直接使用系统自带的Login控件,需要做2项修改工作:
  1、根据你选用的数据库,修改Web.config中相应的connectionStrings。系统默认的数据库是SQL Server 2005 Express,如果我们的数据库是Access/SQL2000/2005/Oracle,当然要大改一番了。
  2、改完Web.config还不够,我们还得执行C:/WINNT/Microsoft.NET/Framework/v2.0.507/aspnet_sqlreg.exe注册你的sql server,该程序的作用是在你的数据库中建立Login控件需要的所有资源(大约有上十个表,三十多条存储过程,上十个视图等等),如果你使用的是access/orcale,或者是其他格式的数据库,那你自己去Google相应的SQL脚本吧。
  OK,想到Login控件帮你节省的工作量,相信不少人都会咬着牙完成上面的2项工作。完成上面2项工作后,大家接着读项目需求,发现有用户组管理和权限管理,幸好开发资料上提到Login控件集成的Role角色管理模块正好与之对应,不过以后我们创建一个用户后,还要再进入一个页面给用户选择所属用户组,当然,采用Role的话,我们可以设定一个用户同时属于多个用户组,貌似功能很强大哟。继续读项目需求,发现这些项目的用户对象还有不少Login控件中没有的属性要保存,回头再去翻MSDN,发现Profile可以帮我们解决这个问题。
  嗯,除开使用Login控件,运行aspnet_sqlreg.exe帮我们建立的上十个表,三十多条存储过程,上十个视图等,我们再不用建表保存用户的任何信息了,以后我们只用在Web.config文件和相应的cs代码中加上Role和Profile的处理代码,即可完成该项目的登陆,用户管理,密码修改功能。算算投入查MSDN,Google及修改Web.config文件和相应的cs代码的时间,相信原来自己写过自定义Login控件的朋友已经准备发誓再也不碰Asp.net 2.0自带的Login控件了。
  其实,我们完全有更简洁通用的办法来重用Asp.net 2.0自带的Login控件,即只用它最基本的登陆及修改密码功能,这2个基本功能照旧从工具箱拖个控件出来往Web表单上一扔即可,一行代码都不多加。其他的用户/用户组管理,权限管理不用扯上Login控件,数据库想用什么产品就用什么产品,mysql/db2/infomax来者不拒;表结构想怎么设计就怎么设计,E-R图,UML图直接照搬就成;用户/用户组管理和权限管理模块想怎么规定就怎么规定,自关联,无限分级都行。总之一句话:让Login控件附带的上十个表,三十多条存储过程,上十个视图见鬼去吧。
  下面细说实现方法,Asp.net 2.0的Login控件用到了3个类来从数据库中获取相应的数据,分别是MemberShipprovider,RoleProvider及ProfileProvider,系统自带的这3个类的方法的代码被隐藏起来了,尽管没公开,但实际上就是使用我上面一直念叨的上十个表,三十多条存储过程,上十个视图。不管你用什么数据库,只要想使用Login控件的所有功能,必须保证该数据库中有与之对应的十来个表,三十多条存储过程,十来个视图。
  当然,MS的架构设计师也不是某些人想象中的那么无能,上面的这三个类其实都是抽象类,系统的Login控件实际调用的是从这3个类派生出来的针对SQL Server2000/2005的数据操作类,灵活的架构设计正是在这里体现出来。既然MemberShipProvider,RoleProvider及ProfileProvider三大头是抽象类,那么我们完全可以自定义一个只针对用户表的username及password2个列操作的MemberShipprovider派生类出来,重写登陆验证,修改密码以及其调用的方法,然后在Web.config中把membership的提供者指定为我们自己写的MemberShipprovider派生类,这样我们就可以和原来一样,把Login控件的登陆和修改密码2个子控件往Web表单上一拖了事。
  下面开始贴代码,懒的深究的朋友们可以直接把我给出的cs代码贴回去,建个cs文件放到App_Code目录下,然后按照后面的Web.config修改相应的connectionStrings和membership即可,以后任何项目要利用Asp.net 2.0的Login控件的登陆和修改密码都是这样照葫芦画瓢,够傻瓜吧。

 

using  System;
using  System.Data;
using  System.Configuration;
using  System.Data.SqlClient;
using  System.Collections.Generic;
using  System.Text.RegularExpressions;
using  System.Data.SqlTypes;
using  System.Web;
using  System.Web.Security;

/// <summary>
/// MyMemberShip 的摘要说明
/// </summary>

public   class  MyMemberShip : MembershipProvider
{
    
private bool _requiresQuestionAndAnswer;
    
private int _minRequiredPasswordLength; 
    
public MyMemberShip()
    
{
        
//
        
// TODO: 在此处添加构造函数逻辑
        
//
    }

    
public override string ApplicationName
    
{
        
get
        
{
            
throw new Exception("The method or operation is not implemented.");
        }

        
set
        
{
            
throw new Exception("The method or operation is not implemented.");
        }

    }

    
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
    
{

        
if (config["requiresQuestionAndAnswer"].ToLower() == "true")
            _requiresQuestionAndAnswer 
= true;
        
else
            _requiresQuestionAndAnswer 
= false;
        
int.TryParse(config["minPasswordLength"], out _minRequiredPasswordLength);
        
base.Initialize(name, config);
    }

    
public override bool ChangePassword(string username, string oldPassword, string newPassword)
    
{
        
using (SqlConnection connection = new SqlConnection(DBBase.DBConnectionString))
        
{
            SqlCommand command 
= new SqlCommand();
            command.CommandText 
= "update [User] set user_pwd=@newpwd where user_name=@name and user_pwd=@oldpwd";
            command.Parameters.AddWithValue(
"@name", username);
            command.Parameters.AddWithValue(
"@oldpwd", CryptUtil.GetStringHashValue1(StringUtil.SqlEscape(oldPassword)));
            command.Parameters.AddWithValue(
"@newpwd", CryptUtil.GetStringHashValue1(StringUtil.SqlEscape(newPassword)));
            command.Connection 
= connection;
            connection.Open();
            
return (int)command.ExecuteNonQuery() > 0 ? true : false;
        }

        
//throw new Exception("The method or operation is not implemented.");
    }


    
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override bool DeleteUser(string username, bool deleteAllRelatedData)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override bool EnablePasswordReset
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override bool EnablePasswordRetrieval
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override int GetNumberOfUsersOnline()
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override string GetPassword(string username, string answer)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override MembershipUser GetUser(string username, bool userIsOnline)
    
{
        DateTime myDate 
= DateTime.Today;
        MembershipUser user 
= new MembershipUser(
        Name, 
// Provider name
        username, // Username
        null// providerUserKey
        bobcy@21cn.com// Email
        String.Empty, // passwordQuestion
        String.Empty, // Comment
        true// isApproved
        false// isLockedOut
        DateTime.Now, // creationDate
        DateTime.Now, // lastLoginDate
        DateTime.Now, // lastActivityDate
        DateTime.Now, // lastPasswordChangedDate
        new DateTime(198011// lastLockoutDate
        );
        
return user; 
    }


    
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override string GetUserNameByEmail(string email)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override int MaxInvalidPasswordAttempts
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override int MinRequiredNonAlphanumericCharacters
    
{
        
get return 0; }
    }


    
public override int MinRequiredPasswordLength
    
{
        
get return _minRequiredPasswordLength; } 
    }


    
public override int PasswordAttemptWindow
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override MembershipPasswordFormat PasswordFormat
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override string PasswordStrengthRegularExpression
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override bool RequiresQuestionAndAnswer
    
{
        
get return _requiresQuestionAndAnswer; }
    }


    
public override bool RequiresUniqueEmail
    
{
        
get throw new Exception("The method or operation is not implemented."); }
    }


    
public override string ResetPassword(string username, string answer)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override bool UnlockUser(string userName)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override void UpdateUser(MembershipUser user)
    
{
        
throw new Exception("The method or operation is not implemented.");
    }


    
public override bool ValidateUser(string username, string password)
    
{
        
using (SqlConnection connection = new SqlConnection(DBBase.DBConnectionString))
        
{
            SqlCommand command 
= new SqlCommand();
            command.CommandText 
= "select count(0) from [User] where user_name=@name and user_pwd=@pwd";
            command.Parameters.AddWithValue(
"@name", username);
            command.Parameters.AddWithValue(
"@pwd", password);
            command.Connection 
= connection;
            connection.Open();
            
return ((int)command.ExecuteScalar()) > 0 ? true : false;
        }

    }

}

 

Web.Config的membership节这样写,connectionStrings和数据库有关,不同的数据库差别很大,大家自己Google,我就不列出来了。

         < membership  defaultProvider ="MyMemberShip" >
            
< providers >
                
< clear />
                
< add  name ="MyMemberShip"  type ="MyMemberShip"  requiresQuestionAndAnswer ="false"  connectionString ="AdminSqlServer"  minRequiredNonalphanumericCharacters ="0"   />
            
</ providers >
        
</ membership >

  如果我们想在用户验证登陆成功后做一些额外的处理,可以给登陆控件的登陆按钮添加一个事件,,相应的代码如下:

 

     protected   void  Login1_Authenticate( object  sender, AuthenticateEventArgs e)
    
{
        
if (Membership.ValidateUser(Login1.UserName, Login1.Password))
        
{
            
//这里添加你的额外处理代码,如Session,login日至等等
            e.Authenticated = true;
        }

    }

 

  如果还想重用Login控件的其他功能,但不想按照系统附带的数据库设计的话,还可以按照你的项目的数据库设计重写RoleProvider和ProfileProvider2个抽象类,对这方面资料感兴趣的朋友可以看看下面这篇文章(重写了几个RoleProvider的方法),更多资料请自行查阅MSDN及Google:
http://www.lemongtree.com/Archives/2006/11/28/0000572.aspx

  不过我个人的经验来看,每个项目的用户管理和权限管理都不尽相同,有的甚至差别很大,重写RoleProvider和ProfileProvider的重用价值不大。

修改ASP.NET 2.0 CreateUserWizard的控件的密码长度 在用ASP.NET 2.0的CreateUserWizard的控件时,有个很郁闷的问题:默认的注册密码需要密码长度为7且最少一个非字母数字字符. 好像大部分人都没用"!", "@", "_",做密码的习惯. 下面提供修改上需问题的方案: 在web.config文件 <system.web><system.web> 中添加以下代码 如果你觉得手动输入上面代码太麻烦... 阅读详情

相关推荐

Membership学习(三)Membership Providers介绍[xgluxv]

本来想在第三篇文章里介绍一下 Membership的类的,不过现在中文msdn也出来了,所以就不写了,,直接到介绍Membership Providers。 Membership Providers提供了Membership数据源服务之间的所有接口,在Asp.net2.0中提供了两个Provider:SqlMembershipProviderActiveDirectoryMe...

weixin_30872733的博客 230

Membership学习(三)Membership Providers介绍

本来想在第三篇文章里介绍一下 Membership的类的,不过现在中文msdn也出来了,所以就不写了,,直接到介绍Membership Providers。 Membership Providers提供了Membership数据源服务之间的所有接口,在Asp.net2.0中提供了两个Provider:SqlMembershipProviderActiveDirectoryMembe...

weixin_30783913的博客 168

自定义成员资格提供程序(MemberShip Provider)实现与角色提供程序(Role Provider)实现示例

本文内容转自 MSDN,Junelf 将两篇文章合并为一篇并稍作总结。ASP.NET 成员资格旨在使您可以轻松地将多个不同的成员资格提供程序与多个不同的角色提供程序用于您的 ASP.NET 应用程序。您可以使用 .NET Framework 中包含的成员资格提供程序,也可以实现自己的提供程序。在实现自定义成员资格提供程序时,需要继承 MembershipProvider 抽象类;实现自定义

Junelf's BLOG 5500

ASP.NET身份验证机制membership入门——项目

前面说了很多关于membership的内容,感觉内容有点凌乱,内容都是一个个知识点,下面我们通过一个小的项目,来把所有的相关内容串一下。     首先描述一下需求:   我们要做一个最简单的网站。有三类用户:匿名用户,员工,管理员,网站结构如下:           admin目录下的页面只允许admin角色的用户访问,employee目录下的页面只允许emp角色的用户访问。De...

fhuan123的专栏 231

ASP.net Membership角色与权限管理

本文目录:1.membership简介2.membership在sql server中的设置3.配置web.config4.创建用户CreateUserWizard控件5.用户登录login控件6.显示当前用户的名称LoginName控件7.检测用户的身份验证状态的LoginStatus控件8.为不同类别用户呈现不同内容的LoginView控件9.更改密码的ChangePassword控件10.自助找回密码的PasswordRecovery控件11.总结1.membership简介membership,真的

niufujiang008的专栏 1362

EntityFramework Core连接国产达梦数据库

近期意外发现了国产达梦数据库.NET Core环境下EFCore的支持,把测试过程分享如下。 1.测试环境 .Net Core 2.1 EntityFramework Core 2.2.4 DM v8(达梦) Window 10 x64 2.踩坑记录 近些年数据库等基础设施国产化的呼声越来越高,达梦也算国产数据库中知名度较高的了,不过开发生态环境还不够完善,使用过程中也是各种坑。 2.1达...

lordwish的专栏 7384

Membership学习(四)-自定义MembershipProvider[xgluxv]

自定义MembershipProvider:前面讲了内置的MembershipProvider,这次 我们自己定义一个Provider。首先我们确定一下保存数据使用ms 的access,好像土了点。 我还是用一个例子来说明: 启动 vs2005,创建一个Asp.net Web Site,名字就取一个NewMembershipProvider,在App_Data目录里 ...

weixin_30519071的博客 196

MembershipProviders以及数据库结构介绍

MembershipProviders以及数据库结构介绍所属类别:ASP.net推荐指数:★★★☆文档人气:143本周人气:8loadDocInfo(3142);发布日期:2008-3-9本来想在第三篇文章里介绍一下 Membership的类的,不过现在中文msdn也出来了,所以就不写了,,直接到介绍Membership Providers。

liaozhiweihaifeng的专栏 518

MemberShip加密处理方式

先看一下Code:static void Main(string[] args) { string password = "******"; //[这里密码就不写出来了] string salt = "OoBH7KjGqLNjM9MsSeKV4w=="; Console.WriteLine(Enco

Michael.M的专栏 3663

Windows 10修改登录背景(Win10BGChanger)

默认情况,用户无法直接修改Windows 10的登录背景,但用户还是可以利用第三方的工具(W10 Logon BG Changer)来修改。(软件下载地址见附件)下载后,解压缩,然后以管理权限运行GUI文件夹下的W10 Logon BG Changer程序,出现如下界面:在窗口右侧编辑背景下选择本地背景,或者选择其它颜色作为背景。还可以设置图像缩放。选择完成后,点击应用更改即可。同时,还可以恢复默...

weixin_33866037的博客 679

自定义MembershipProvider

自定义MembershipProvider:前面讲了内置的MembershipProvider,这次 我们自己定义一个Provider。首先我们确定一下保存数据使用ms 的access,好像土了点。       我还是用一个例子来说明:       启动 vs2005,创建一个Asp.net Web Site,名字就取一个NewMembershipProvider,在App_Data目录里 建一个

sytWeibo的专栏 1167

ASP.NET Security Provider实现(一)ASP.NET Provider

ASP.NET Provider 从ASP.NET2.0中,提供了各类的provider,有membership,role,profile等的,可以很方便地实现如角色,用户等管理,甚至不用自己写代码了。这些provider在ASP.NET 4.0ASP.NET MVC中同样适用。 System.Web.Security.MembershipProvider类 定义 ASP....

dbmdi5530的博客 210

浅析ASP.NET 2.0的用户密码加密机制

摘要: 1 加Salt散列 2 ASP.NET 2.0 Membership中与密码散列有关的代码 声明:本文所罗列之源代码均通过Reflector取自.NET Framework类库,Anders Liu引用这些代码仅出于学习研究的目的。 前一段关于密码的存储问题产生了一些讨论。我所看到的景象是,首先在cnbeta新闻中提到中国某银行将强制冻结密码过于简单(如6个8)的帐户,引发了争论...

weixin_30852419的博客 384

Active Directory Membership Provider

ASP.NET 2.0 allows you to validate users via Active Directory, database, or even a custom algorithm. ASP.NET 2.0 supports a provider-based model for a number of application services inclu...

weixin_33755847的博客 201

asp.net 服务器端的验证控件——密码修改验证

只是在页面进行简单的验证。                             用户名称:                                                                原始密码:                                                        新 密 码:                   

阿强的一亩三分地,一分耕耘一分收获 3644
上一篇: 采用左右值编码来存储无限分级树形结构的数据库表设计
下一篇: 最全中文时区表(从Google日历中挖出来的)
comiunknown
博客等级 码龄22年 58粉丝 36原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值