Membership角色与权限管理-程序员宅基地

技术标签: 项目管理  ASP.net  SQL Server  配置管理  ASP  

Membership角色与权限管理
http://www.blueidea.com/tech/program/2007/4676.asp

http://www.shehui001.com/map.asp?pid=1273


Membership学习(一) Membership介绍
Asp.net的membership提供了一种存储,验证和管理用户信息以及权限的统一的路径。membership所对应的验证方式是asp.net的Forms身份验证(注:asp.net的身份验证方式 有好几种包括windows身份验证 Forms身份验证 Passport身份认证当然还有就是没有验证)。在vs2005中 还给membership提供了一系列的控件(login控件),能方便的在asp.net实现membership。
具体来说membership能实现:
1. 创建用户
2. 可以保存membership信息在sql server,Active Directory以及其他的一些数据保存方法
3. 鉴别谁在访问你的网站。如果使用login控件,几乎可以在不写代码的情况下完成。
4. 管理密码。包括 创建 修改 重置
5. 创建一个唯一的值来标志每一个登陆用户,可以实现对用户的个性化以及角色管理。
6. 提供一个用户自定义的membership provider,从而实现一些自己网站特有的数据的保存和管理。
让membership能工作要做的一些工作:
1. 在web.config中填写一些membership的设置,在asp.net默认情况下membership是被允许使用的 而默认的数据保存是使用ms的sql server.你可以做些设置提供其他的数据保存方法 包括自定义的方法。这将在后面的文章中具体介绍
2. 设置你的网站使用Forms验证方式,
3. 为membership定义用户帐号。可以使用vs2005提供的web administrator tool进行设置,也可以自己制作create user页面进行,而自定义页面 只要调用membership.createuser就可以方便的创建用户。

Membership的管理和配置:
在web.config中配置管理membership最简单的方法就是使用Web Site Administration Tool(在vs2005的websits菜单里)。你可以指定membership的提供者sql server还是其他,密码的管理 包括是否要加密保存 以及是否要给用户提供根据事先设置的问题 恢复密码的机制。当然是用web site administration tool可以直接创建和管理用户及角色。

Membership的方便之处在于,当一个用户通过认证之后,他的信息的保存都是系统自动完成的 这样我以前最头痛的如何安全完整的在各个页面中传递登陆用户信息这点就迎刃而解了。
如果使用vs2005自带的login控件 要清楚一件事 就是login控件的功能实现都是调用了membership的类函数,我们完全可以自己写出所有的控件。
之后会具体介绍membership的使用。我的介绍也是对msdn的一些翻译和整理。
Membership学习(二)membership入门
--不写一行代码在asp.net中实现用户验证管理系统
这篇文章我们将实现一个简单的网站,在网站中实现用户的身份验证,创建用户,修改密码 还有限制匿名用户访问某些目录等功能,最神奇的是使用asp.net2.0实现我们几乎不用手工写一行代码。--不知道以后程序员要做些什么事了:(!!

我们手工从头创建一个web应用,学习其中的一些技术,这个应用将要完成的任务有
1. 创建一个包含membership服务的web应用,创建一个用户
2. 使用login控件,得到用户的凭证以及显示登录用户的信息
3. 在网站里创建一个目录 里面的页面只有登录用户才能访问
4. 允许网站创建新用户
5. 用户可以修改和重置
我的开发环境windows2003,iis6.0,vs2005 team suit英文版,sql server2005 express

工作开始
一、在本地IIS上创建一个网站
1. 打开visual studio,file菜单,选择 New web site
2. 选择asp.net web site,在location下来框里选择http,然后点击browser按钮,在弹出框里选择local IIS,打开Local Web Server,选择默认网站(default web site),点击对话框右上的Create New Web Application图标,命名为membership,点击open按钮关闭对话框。
3. 选择工作语言(c#等),以后在创建其他网页时 可以选择不同的语言 :)
4. 点击OK
网站创建后 会默认生成一个default.aspx页面 我们留着他就可以了,也可以删除他 重新创建一个页面
二、配置membership
1. 创建一个新的文件夹在网站里命名为MemberPages
2. 创建一个membeship用户
a. 在菜单website里选择Asp.net configuration,在打开的网页里选择Security tab页,点击Use the security Setup Wizard to configure security step by step链接。
b. 在向导第2步里选择 From the Internet 选项 这里是让你的网站使用Form的身份认证,原因在membership介绍 文章里讲过。
c. 点击Next 这步还是默认使用sql server2005 express并会在App_Data目录里生成数据库文件。
d. 点击Next 这里不要选择Enable roles for this web site
e. 点击Next 这时是创建一个用户 输入User Name ,Password,,E-mail, Security Question and Security Answer ,创建用户。这里顺便说一下 membership默认的密码设置是比较严格的需要字母数字加特殊字符,其实我们可以在web.config中给membership的密码指定一个正则表达式 来修改密码的规则。具体可以在msdn中查找
3. 创建一个规则 限制访问一个指定的目录
a. 接着刚才的向导继续next,进入创建访问规则页面,在显示网站目录的框里,展开目录,选择刚才我们创建的MemberPages的文件夹。
b. 在Rule applies to下选择Anonymous users,在Permission下选择deny,这样就限制了匿名用户访问目录的权限。
c. 点击add this rule权限创建,接着是Finish.
三、为应用配置一个E-mail
这个操作的目的是为了恢复密码时发送密码给用户
还是在asp.net configuration的网页里 选择Application tab页面,在Smtp Settings下 点击Configure SMTP e-mail settings.链接,这个配置一个smtp服务器以及一个email账号。
配置完email就可以关闭 这个配置页面了。
四、用户登录
打开default.aspx页面,使用design视图,在上面写个welcome什么的,然后拖上一个login控件组里的loginstatus控件。接着建一个login.aspx页面,在这个例子里我们的页面的名字一定要取成login.aspx,在默认情况下 当匿名用户访问受限制的页面时,会自动转到login.aspx,这个默认设置可以通过配置更改的,这里我们就使用默认。
在login.aspx页面上拖放一个login控件组里的login控件,再放置一个ValidationSummary控件,用来现实填写的出错信息,将ValidationSummary的ValidationGroup属性设置成login控件的id名称。

显示登录用户信息
选择default.aspx页面拖上一个loginview控件,使用loginview智能标签(smart tag),选择模板AnonymousTemplate,写上”你没有登录,点击login链接登录”,然后再选择模板LoggedInTemplate,写上”欢迎”字符,再在后面拖上一个loginname控件。
这之后,你可以先测试一下你的页面 使用我们上面建立的用户进行登录,看看不同的显示。
五、建立只能用户访问的页面
在我们上面建立的MemberPages文件夹里建立一个Members.aspx页面,写上welcome member,然后 我们在default.aspx页面上拖一个HyperLInk控件,在NavigateUrl属性里写上~/memberPages/Members.aspx
这里也可以进行一次测试
六、创建新用户
在根目录里建立一个register.aspx,在页面上拖放一个CreateUserWizard控件并把它的ContinueDestinationPageUrl属性设置成~/default.aspx,这个属性是对你点击Finish之后跳转的页面。接着在页面里添加一个Hyperlink控件,NavigateUrl设置成~/default.aspx.最后在default.aspx页面里添加一个指向register.aspx页面的链接,为了好看一点 我们把这个链接放到loginview控件的AnonymousTemplate模板里。
测试一下
七、修改密码
在MemberPages文件夹里创建一个ChangePassword.aspx文件,拖上一个ChangePassword控件也把它的ContinueDestinationPageUrl属性设置成~/default.aspx。接着在default.aspx页面里添加一个指向changepassword.aspx页面的链接, 我们把这个链接放到loginview控件的LoggedInTemplate模板里。
测试
八、重置密码
在根目录里建立一个recoverypassword.aspx文件,拖一个passwordrecovery控件,并放一个链接指向default.aspx.之后在default.aspx的loginview控件的AnonymousTemplate模板里添加一个链接指向recoverypassword控件。
测试

这样整个例子完成 大家也可以看到 我们没有写一行代码。:)
本来想在第三篇文章里介绍一下 Membership的类的,不过现在中文msdn也出来了,所以就不写了,,直接到介绍Membership Providers。
Membership Providers提供了Membership数据源和服务之间的所有接口,在Asp.net2.0中提供了两个Provider:SqlMembershipProvider和ActiveDirectoryMembershipProvider,从命名中我们也可以看出,SqlMembershipProvider是把 sql server和sql server express数据库作为数据库源,而ActiveDirectoryMembershipProvider是有Microsoft Active Directory(活动目录)作为数据源的。
Membership Providers的基本工作是用来管理一个网站注册用的数据,并且提供一些函数用来做 创建,删除用户,验证用户登录信息,修改密码等工作。在.net 框架的System.Web.Security命名空间下有一个MembershipUser的类,这个类定义了Membership 用户的一些基本属性,Membership Provider用这个类来描绘每个用户信息。Membership Providers 有一个基础类 他的定义如下:(丛msdn里copy出来的)

public abstract class MembershipProvider : ProviderBase
{
// Abstract properties
public abstract bool EnablePasswordRetrieval { get; }
public abstract bool EnablePasswordReset { get; }
public abstract bool RequiresQuestionAndAnswer { get; }
public abstract string ApplicationName { get; set; }
public abstract int MaxInvalidPasswordAttempts { get; }
public abstract int PasswordAttemptWindow { get; }
public abstract bool RequiresUniqueEmail { get; }
public abstract MembershipPasswordFormat PasswordFormat { get; }
public abstract int MinRequiredPasswordLength { get; }
public abstract int MinRequiredNonAlphanumericCharacters { get; }
public abstract string PasswordStrengthRegularExpression { get; }
// Abstract methods
public abstract MembershipUser CreateUser (string username,
string password, string email, string passwordQuestion,
string passwordAnswer, bool isApproved, object providerUserKey,
out MembershipCreateStatus status);
public abstract bool ChangePasswordQuestionAndAnswer
(string username, string password,
string newPasswordQuestion, string newPasswordAnswer);
public abstract string GetPassword (string username,
string answer);
public abstract bool ChangePassword (string username,
string oldPassword, string newPassword);
public abstract string ResetPassword (string username,
string answer);

public abstract void UpdateUser (MembershipUser user);
public abstract bool ValidateUser (string username,
string password);
public abstract bool UnlockUser (string userName);
public abstract MembershipUser GetUser (object providerUserKey,
bool userIsOnline);
public abstract MembershipUser GetUser (string username,
bool userIsOnline);
public abstract string GetUserNameByEmail (string email);
public abstract bool DeleteUser (string username,
bool deleteAllRelatedData);
public abstract MembershipUserCollection GetAllUsers
(int pageIndex, int pageSize, out int totalRecords);
public abstract int GetNumberOfUsersOnline ();
public abstract MembershipUserCollection FindUsersByName
(string usernameToMatch, int pageIndex, int pageSize,
out int totalRecords);
public abstract MembershipUserCollection FindUsersByEmail
(string emailToMatch, int pageIndex, int pageSize,
out int totalRecords);
// Virtual methods
protected virtual byte[] EncryptPassword (byte[] password);
protected virtual byte[] DecryptPassword (byte[] encodedPassword);
protected virtual void OnValidatingPassword
(ValidatePasswordEventArgs e);
// Events
public event MembershipValidatePasswordEventHandler
ValidatingPassword;
}


SqlMembershipProvider类就是从这个类里继承下来的。
接下来 我们使用SqlMembershipProvider类作为例子来进行比较细致的说明。
SqlMembershipProvider:
SqlMembershipProvider是给Membership使用sql server数据库做的Provider,它使用数据库的存储过程来实现对数据的操作,这样SqlMembershipProvider可以经过很少的改动来 实现对其他数据库的支持。
1.Provider 初始化
Provider初始化是在 SqlMembershipProvider.Initialize,它只运行一次,是在asp.net装载Provider时。
a.初始化SqlMembershipProvider的各种属性 比如:EnablePasswordRetrieval 和 EnablePasswordReset,从相应的配置文件的配置属性中读入。
b.对一些公共属性的值进行检查,当有错误的时候抛出异常,比如PasswordFormat值是”hashed”,而EnablePasswordRetrieval的值是true,就会有异常抛出。
c.在配置里存在一些不被承认的属性时,也会抛出异常
SqlMembershipProvider.Initialize还会从<connectionStrings>中读取数据库连接字符串,保存到一个私有的变量中,如果不能读到或者读取的连接字符串是错误的,也会抛出一个异常。
2.数据定义
SqlMembershipProvider的Membership数据保存在数据库的aspnet_Membership表中
aspnet_Membership 定义(msdn中取出)
字段名 字段类型 表述
ApplicationId uniqueidentifier Application ID,应用程序id
UserId uniqueidentifier User ID,用户id
Password nvarchar(128) 密码,可以是加密 hash保存的
PasswordFormat int Password format (0=Plaintext, 1=Hashed, 2=Encrypted)
PasswordSalt nvarchar(128) Randomly generated 128-bit value used to salt password hashes; stored in base-64-encoded form
MobilePIN nvarchar(16) User's mobile PIN (当前没有使用)
Email nvarchar(256) email
LoweredEmail nvarchar(256) 小写email地址
PasswordQuestion nvarchar(256) 密码问题
PasswordAnswer nvarchar(128) 密码问题答案
IsApproved bit 1=Approved, 0=Not approved
IsLockedOut bit 1=Locked out, 0=Not locked out
CreateDate datetime 创建时间
LastLoginDate datetime 最后登录时间
LastPasswordChangedDate datetime 密码最后修改时间
LastLockoutDate datetime 最后登出的时间
FailedPasswordAttemptCount int 联系登录失败次数
FailedPasswordAttempt-WindowStart datetime 在FailedPasswordAttemptCount非零时,第一次登录失败的时间

FailedPasswordAnswer-AttemptCount int 回答密码问题联系失败的次数
FailedPasswordAnswer-AttemptWindowStart datetime 在FailedPasswordAnswer-AttemptCount非零时,第一次回答问题失败的时间
Comment ntext 扩展的文本

这个表中的每一条记录代表一个用户,这个表还有两个外键,分别关联aspnet_Applications表和aspnet_Users表
aspnet_Applications表
字段名 字段类型 描述
ApplicationId uniqueidentifier Application ID
ApplicationName nvarchar(256) Application name
LoweredApplicationName nvarchar(256) Application name (小写)
Description nvarchar(256) Application 描述
aspnet_Users 表
字段名 字段类型 描述
ApplicationId uniqueidentifier Application ID
UserId uniqueidentifier 用户ID
UserName nvarchar(256) 用户名
LoweredUserName nvarchar(256) 用户名 (小写)
MobileAlias nvarchar(16) User's mobile alias (currently not used) 没有使用
IsAnonymous bit 1=Anonymous user, 0=Not an anonymous user
LastActivityDate datetime 用户最后一次活动时间
一条完整的记录 aspnet_Membership和aspnet_Users都要存在。
3.数据访问
SqlMembershipProvider是通过存储过程完成所有的数据库操作的,简单介绍一下这些存储过程
SqlMembershipProvider存储过程
名称 描述
aspnet_Membership_ChangePassword-QuestionAndAnswer 修改密码,密码问题,密码问题答案
aspnet_Membership_CreateUser 增加一个membership用户 记录同时写入aspnet_Users 和aspnet_Membership 表, 如果需要,还要增加一条记录到aspnet_Applications表。
aspnet_Membership_FindUsersByEmail 通过email地址匹配查找用户的记录,同时还要一个application ID.
aspnet_Membership_FindUsersByName 通过用户名匹配查找用户的记录,同时还要一个application ID.
aspnet_Membership_GetAllUsers 得到所有用户记录,在一个下application ID.
aspnet_Membership_GetNumberOfUsersOnline 得到在线用户数 (通过用户最后活动时间字段(LastActivityDate)实现)
aspnet_Membership_GetPassword 得到一个用户的密码,通过密码问题的回答
aspnet_Membership_GetPasswordWithFormat 得到一个用户的密码。通过密码比较重新取得密码。
aspnet_Membership_GetUserByEmail 使用email和application id从aspnet_Membership中得到相应的记录
aspnet_Membership_GetUserByName 使用用户名和application id从aspnet_Membership中得到相应的记录
aspnet_Membership_GetUserByUserId 使用userid和application id从aspnet_Membership中得到相应的记录
aspnet_Membership_ResetPassword 重置用户密码通过回答密码问题
aspnet_Membership_SetPassword 设置一个密码
aspnet_Membership_UnlockUser 恢复用户登录的权限通过将IsLockedOut字段设置成0
aspnet_Membership_UpdateUser 更新用户的aspnet_users表的LastActivityDate,e-mail,注释,approved字段和aspnet_Membership表的最后登录时间。
aspnet_Membership_UpdateUserInfo 更新帐户锁定时间在aspnet_users和aspnet_Membership表,Used in conjunction with provider methods that track bad password and bad password-answer attempts.

aspnet_Users_CreateUser 调用aspnet_Membership_CreateUser增加一个到用户到aspnet_users表。

aspnet_Users_DeleteUser 删除一个用户 从aspnet_membership已经一些关联表里包括aspnet_users.

4.创建用户
SqlMembershipProvider.CreateUser通过调用aspnet_Membership_CreateUser储存过程创建membership用户。SqlMembershipProvider.CreateUser在调用存储过程之前还会对用户的输入参数做一些校验,包括密码等。
创建用户的流程
a. 调用aspnet_Applications_CreateApplication,存储过程,转换一个ApplicationName成Application ID.如果在aspnet_Applications表中已经存在这个Application ID就返回存在Application ID,如果表中不存在,在aspnet_Applications表中新增加一条记录并返回这个Application ID.
b. 调用aspnet_Users_CreateUser在aspnet_Users表中添加一条新记录
c. 做一个验证对email地址和原来已经注册的用户。
d. 使用当前的时间来更新一下aspnet_Users表的LastActityDate字段。
e. 插入一条新记录到aspnet_Membership表。
aspnet_Membership_CreateUser提供了所有的这些步骤,并使用事务来保证数据库更新的完整性。

5.删除用户
程序通过调用Membership.DeleteUser来实现删除membership用户的功能。
Membership.DeleteUser调用默认的membership提供者的DeleteUser的函数,而这个函数有两个输入值,一个是用户名 另外一个参数(deleteAllRelatedData)是bool值,这个bool值表示是否要删除这个用户的一些关联信息,包括role data, profile data和 Web Parts personalization data。
DeleteUser还可以实现一个其他的功能就是 把用户名输入Request.AnonymousID,而参数deleteAllRelatedData设置为true,这样可以删除匿名用户在数据库的aspnet_Profile和aspnet_Users表中保存的记录。
6.验证membership用户
程序通用调用Membership.ValidateUser来实现用户的验证,返回值是一个bool值,包括用户名密码是否正确。
验证的流程
a. 通过调用存储过程 aspnet_Membership_GetPasswordWithFormat得到用户的密码,如果是加密的返回的是加密的字串。
b. 使用相同的加密码方法加密输入的密码。
c. 比较两个密码。
d. 如果密码匹配 会触发一个AuditMembershipAuthenticationSuccess的Web 事件,同时记录一个成功登陆的纪录,并返回true
e. 如果密码不匹配,会触发一个 AuditMembershipAuthenticationFailure的web 事件,返回false,同时还会调用aspnet_Membership_UpdateUserInfo储存过程做记录,如果记录发现已经达到限制用户登录的条件,还会锁住此用户。
7.密码保护
为了安全,密码保存在数据库中一般不用明文,SqlMembershipProvider提供了几种不同保存密码的方法,我们可以通过设置PasswordFormat属性来指定不同的保存方法。
a. MembershipPasswordFormat.Clear使用明文保存
b. MembershipPasswordFormat.Hashed 默认参数,会使用.Net框架的RNGCryptoServiceProvider类来对密码和密码问题进行Hash计算保存。
c. MembershipPasswordFormat.Encrypted对密码和密码问题进行加密。SqlMembershipProvider使用的是对称密钥加密方法。加密的密钥保存在<machineKey>配置字段里
为了增加一些额外的安全保护,SqlMembershipProvider还提供了MinRequiredPasswordLength,MinRequiredNonAlphanumericCharacters,PasswordStrengthRegularExpression三个属性来加强保护,根据字面意思应该是密码最小长度,最少特殊字符数,密码正则表达式。
8.帐户锁定
为了抵御穷举密码 猜密码的攻击,SqlMembershipProvider提供了一个自动锁定用户的机制,当一个帐户在一段时间内连续登录失败超过一定次数后,这个用户将被锁定,SqlMembershipProvider的MaxInvalidPasswordAttempts和PasswordAttemptWindow属性,默认MaxInvalidPasswordAttempts=5次,PasswordAttemptWindow=10分钟。当数据表里的IsLockedOut=1时用户就被锁定了。
对Membership Provider等Provider微软提供了源代码,但这些源代码和.Net框架里包含的是有区别的,主要是为了能让提供的源代码能让用户独立的编译和运行。
今天这篇文章写的太长,自己都有点晕了,有错误的地方多包涵。
自定义MembershipProvider:
前面讲了内置的MembershipProvider,这次 我们自己定义一个Provider。
首先我们确定一下保存数据使用ms 的access,好像土了点。
我还是用一个例子来说明:
启动 vs2005,创建一个Asp.net Web Site,名字就取一个NewMembershipProvider,在App_Data目录里 建一个Access数据库文件,命名:Members.mdb,创建一个表 名称:MemberShip
字段名 字段类型 描述
username 文本8 用户名 主键
password 文本8 密码
Email 文本50 邮件
passwordQuestion 文本50 密码问题
passwordAnswer 文本50 问题答案

建完表之后,退出Access,备用:)。
我们在网站生成的default.aspx上拖上两个login控件,首先拖上去一个CreateUserWizard控件,不用做什么修改,接着在CreateUserWizard控件下面放上一个LoginView控件,在LoginView的AnonymousTemplate 视图里拖上一个LoginStatus控件,并把LoginStatus控件的LogoutPageUrl设置为login.aspx,login系列控件的应用在我的membership(2)中有比较详细的说明。
接着 我们建一个新的页面 login.aspx 在页面上拖上一个Login控件,准备工作完成。
在项目里新建一个类,命名为AccessMembershipProvider.cs,类的名字 AccessMembershipProvider.继承自MembershipProvider,vs2005会帮我们生成可以重载的函数,我们这里不会建立所有的新函数,,我们重载两个属性和两个函数
首先建几个私有变量
private string connStr;//保存数据库连接字符串
private bool _requiresQuestionAndAnswer;//是否需要问题和回答
private int _minRequiredPasswordLength;//最短密码长度
需要重载的属性为:
MinRequiredPasswordLength 和RequiresQuestionAndAnswer
重载的函数
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
public override bool ValidateUser(string username, string password)
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
下面列出部分的代码:

public override int MinRequiredPasswordLength
{
get { return _minRequiredPasswordLength; }
}
public override bool RequiresQuestionAndAnswer
{
get
{
return _requiresQuestionAndAnswer;
}
}


public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
if (config["requiresQuestionAndAnswer"].ToLower() == "true")
{
_requiresQuestionAndAnswer = true;
}
else
{
_requiresQuestionAndAnswer = false;
}
int.TryParse (config["minRequiredPasswordLength"],out _minRequiredPasswordLength );
connStr = config["connectionString"];
base.Initialize(name, config);
}

public override bool ValidateUser(string username, string password)
{

System.Data.OleDb.OleDbConnection conn=new System.Data.OleDb.OleDbConnection(connStr);
try
{
conn.Open();
string sql = "select * from Membership where username=@username and password=@password";
System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand(sql, conn);
command.Parameters.AddWithValue("@username", username);
command.Parameters.AddWithValue("@password", password);
System.Data.OleDb.OleDbDataReader reader = command.ExecuteReader();

if (reader.HasRows)
{
conn.Close();
return true;
}
else
{
conn.Close();
return false;
}

}
catch
{
if (conn.State == ConnectionState.Open)
conn.Close();
return false;
}

}

public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(connStr);
try
{
conn.Open();
//string sql = "insert into Membership(username,password,Email,passwordQuestion,passwordAnswer) values(@username,@password,@email,@pq,@pa)";
//System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand(sql, conn);
//command.Parameters.AddWithValue("@username", username);
//command.Parameters.AddWithValue("@password", password);
//command.Parameters.AddWithValue("@email", email);
//command.Parameters.AddWithValue("@pq", passwordQuestion);
//command.Parameters.AddWithValue("@pa", passwordAnswer);
//command.ExecuteNonQuery();
MembershipUser user = new MembershipUser("AccessMembershipProvider", username, providerUserKey, email, passwordQuestion, "", isApproved, true, DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now, DateTime.Now);
status = MembershipCreateStatus.Success;
return user;

}
catch
{
if (conn.State == ConnectionState.Open)
conn.Close();
status = MembershipCreateStatus.ProviderError;
return null;
}
}
(上面代码里的数据库操作被我注销掉了,因为它老是提示Inert into语句出错,,嘿嘿 又土了一把)
完成这些代码后 基本上就可以开始测试了,在测试之后我们要建立一个web.config文件在web site中,然后在 <system.web>中填入
<membership defaultProvider="AccessMembershipProvider">
<providers>
<add name="AccessMembershipProvider" type="AccessMembershipProvider" requiresQuestionAndAnswer="true" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\工作\学习例子\NewMembershipProvider\App_Data\Members.mdb;Persist Security Info=False"/>
</providers>
</membership>
DataSource要根据实际路径填写。
将authentication 修改成 <authentication mode="Forms"/>
之后可以启动页面来进行测试了,login控件会根据web.config的配置使用Membership Provider 我们在web.config中defaultProvider中填入了AccessMembershipProvider,它就会用我们自己编写的代码来执行了,你可以修改<add 中的requiresQuestionAndAnswer的值 看看CreateUserWizard控件的显示有什么变化。
例子代码

PS:最近在看BlogEngine.Net的 代码,他们自定义了MemberShip Provider,代码也写的很清晰,如果要学习,可以参考他们的代码,在源代码目录:(source)\BlogEngine.Core \Providers\里的DbMembershipProvider.cs和DbRoleProvider.cs
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sptgreen/article/details/83676501

智能推荐

Webpack生成企业站静态页面 - 项目搭建_webpack打包一个静态网站-程序员宅基地

文章浏览阅读1.2k次,点赞29次,收藏23次。现在Web前端流行的三大框架有Angular、React、Vue,很多项目经过这几年的洗礼,已经都 转型使用这三大框架进行开发,那为什么还要写纯静态页面呢?比如Vue中除了SPA单页面开发,也可以使用nuxt.js实现SSR服务端渲染,满足SEO优化。但是对于那些还是在维护老项目,使用MVC、MVP进行开发,或者觉得使用nuxtjs成本较高小型项目,从历史原因和项目实际情况考虑,会退而求其次,让前端快速完成页面框架和样式,交付后端进行数据渲染。_webpack打包一个静态网站

微信小程序-程序员宅基地

文章浏览阅读1.1k次,点赞30次,收藏27次。WXML(WeiXin Markup Language)是小程序框架设计的一套标签语言,用来构建小程序页面的结构,其作用类似于网页开发中的 HTML。

输入一个Email地址,然后使用正则表达式验证该Email地址是否正确。_输入正确邮箱地址,利用正则表达式pcre判断为正确-程序员宅基地

文章浏览阅读1.2w次。输入一个Email地址,然后使用正则表达式验证该Email地址是否正确 。import java.util.regex.Pattern;import java.util.regex.Matcher;public class Matcherdemo{public static void main(String[] args){String str="[email protected]_输入正确邮箱地址,利用正则表达式pcre判断为正确

龙岩学院计算机专业宿舍,龙岩学院的各个学院位置有谁能说下-程序员宅基地

文章浏览阅读432次。龙岩学院一共有4个学生住宿组团,每个组团有3栋楼。一组团目前居住人文与教育学院、经济管理学院、资源工程学院男生。三组团目前居住物理与机电工程学院、 资源工程学院女生、体育系。今年还搬进了外语系,三组团住的院系最多。四组团目前居住数学与计算机科学学院、生物科学与工程学院。二组团去年住新生、今年好像也有外语院的。1组团8个人一间,有电脑桌,公用行李架。2、3、4组团6人一个房间,有一个浴室、阳台、一人..._龙岩学院计算机科学与技术宿舍

mysql中-e用法_mysql数据库中-e是什么意思?-e参数使用详解-程序员宅基地

文章浏览阅读2.4k次。可以用shell脚本操作mysql数据库,使用mysql的-e参数可以执行各种sql的(创建,删除,增,删,改、查)等各种操作 。用法mysql -hhostname -Pport -uusername -ppassword -e 相关mysql的sql语句,不用在mysql的提示符下运行mysql,即可以在shell中操作mysql的方法。实例:#!/bin/bashHOSTNAME="192...._mysql -h -e

引入随机噪声来模拟真实场景中的噪声:通过概率论的知识,分别讨论两种噪声的生成方式——白噪声和脉冲噪声,并给出相应的算法实现_模拟噪声的算法-程序员宅基地

文章浏览阅读671次。作者:禅与计算机程序设计艺术 1.简介在现实生活中,真实世界中会存在很多类型的噪声,比如说物体抖动、光照变化等等。为了能够更好的理解这些噪声的影响,本文将从实际例子出发,通过算法添加一些随机噪声来模拟这种噪声。首先,对现实世界的背景进行简单的介绍,然后对噪声的类型及其产生原因做详细阐述。之后,将介绍噪_模拟噪声的算法

随便推点

(c语言)圣诞树_c语言圣诞树-程序员宅基地

文章浏览阅读8.4w次,点赞78次,收藏382次。Mooc课后习题集 及 做到的一些有趣的题这是我初学c开始有意识的记录自己做的每一道题开始写下的代码水平 一个一个代码发出来 直到我现在学的数据结构 那个时候还不会注释 格式什么的也是按照自己怎么喜欢怎么来 如果真不会看会代码理解一下 qwq 如代码有错请见谅 毕竟都好久以前敲得了hhh ~~如果对各位的思路引导有帮助那更好#include <stdio.h>int main(){ int i,j,n,space; printf("请输入树的层数:"); scanf_c语言圣诞树

Kafka01_kafka-2.2.1-kafka4.1.0.tar.gz网址-程序员宅基地

文章浏览阅读52次。Kafka文章目录Kafka1. kafka 部署2. kafka 启动脚本编写3. kafka Topic1. kafka 部署消息中间件mysql–>maxwell–>kafka–>ss/flink–>hbase存储数据缓冲上游业务高峰给下游带来的压力作业夯住流式平台发布&订阅: 类似一个消息系统,读写流式的数据处理: 可以编写可扩展的流式app,用于实时事件的响应存储: 副本备份,容错的集群https://docs.cloudera.com/do_kafka-2.2.1-kafka4.1.0.tar.gz网址

植入木马获取网站权限_通过网站获取权限-程序员宅基地

文章浏览阅读1k次。获取网站权限首先获得需操作网址(下面演示的是学校练习靶机)打开网址,利用上篇所讲知识得到后台管理员权限,登入后台管理随机寻找可注入点,找到注入点根目录位置如图,这个就是随机找到的可植入木马位置先写好一个木马文件,即一句话木马<?php @eval($_POST['shell']);?>将以上代码写入webshell.php文件中然后放在站点目录下通过浏览器访问,以POST方式传入shell=phpinfo();,或者用蚁剑或菜刀等工具连接(我这里用的是蚁剑):然后上传至_通过网站获取权限

基于java网上商城源码设计_java电子商城源代码 csdn-程序员宅基地

文章浏览阅读9.3k次,点赞3次,收藏12次。网上图书商城》模型是典型的网上购物实践中最为普遍的电子商务企业对客户(B2C)模式,主要包括会员注册、订单管理、购物车、搜索、支付等基本功能。此外,本系统也将实现在线图书销售系统的后端管理,包括图书的添加、订单的处理等功能。本系统完全基于JSP技术,在系统的设计与开发过程中严格遵守软件工程的规范,运用软件设计模式,从而减少系统模块间的偶合,力求做到系统的稳定性、可重用性和可扩充性。《网上图_java电子商城源代码 csdn

pytorch:融合conv和bn_pytorch导出的conv层权重包含bn层吗-程序员宅基地

文章浏览阅读1.1k次。from copy import deepcopyimport torchimport torch.nn as nndef fuse_conv_and_bn(conv, bn): # Fuse convolution and batchnorm layers https://tehnokv.com/posts/fusing-batchnorm-and-conv/ fusedconv = ( nn.Conv2d( conv.in_channels_pytorch导出的conv层权重包含bn层吗

边界条件(求解偏微分方程的边界条件)-程序员宅基地

文章浏览阅读1.9w次,点赞5次,收藏6次。 研究具体的物理系统,需要考虑研究对象所处的特定的“环境”,而周围环境的影响体现在边界上的物理状况,即边界条件。 常见的线性边界条件,数学上分为三类:第一类边界条件,直接规定了所研究的物理量在边界上的数值;第二类边界条件,规定了所研究的物理量在边界外法线方向上导数的数值;第三类边界条件,规定了所研究的物理量及其外法向导数的线性组合在边界上的数值。(未完待续……)..._偏微分方程的边界条件