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

本来想在第三篇文章里介绍一下 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出来的)

 

None.gifpublic abstract class MembershipProvider : ProviderBase
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
// Abstract properties
ExpandedSubBlockStart.gifContractedSubBlock.gif
    public abstract bool EnablePasswordRetrieval dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract bool EnablePasswordReset dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract bool RequiresQuestionAndAnswer dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract string ApplicationName dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract int MaxInvalidPasswordAttempts dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract int PasswordAttemptWindow dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract bool RequiresUniqueEmail dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract MembershipPasswordFormat PasswordFormat dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract int MinRequiredPasswordLength dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract int MinRequiredNonAlphanumericCharacters dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public abstract string PasswordStrengthRegularExpression dot.gifget; }
InBlock.gif    
// Abstract methods
InBlock.gif
    public abstract MembershipUser CreateUser (string username, 
InBlock.gif        
string password, string email, string passwordQuestion, 
InBlock.gif        
string passwordAnswer, bool isApproved, object providerUserKey,
InBlock.gif        
out MembershipCreateStatus status);
InBlock.gif    
public abstract bool ChangePasswordQuestionAndAnswer
InBlock.gif        (
string username, string password,
InBlock.gif        
string newPasswordQuestion, string newPasswordAnswer);
InBlock.gif    
public abstract string GetPassword (string username,
InBlock.gif      
string answer);
InBlock.gif    
public abstract bool ChangePassword (string username,
InBlock.gif        
string oldPassword, string newPassword);
InBlock.gif    
public abstract string ResetPassword (string username,
InBlock.gif        
string answer);
InBlock.gif 
InBlock.gif    
public abstract void UpdateUser (MembershipUser user);
InBlock.gif    
public abstract bool ValidateUser (string username,
InBlock.gif        
string password);
InBlock.gif    
public abstract bool UnlockUser (string userName);
InBlock.gif    
public abstract MembershipUser GetUser (object providerUserKey,
InBlock.gif        
bool userIsOnline);
InBlock.gif    
public abstract MembershipUser GetUser (string username,
InBlock.gif        
bool userIsOnline);
InBlock.gif    
public abstract string GetUserNameByEmail (string email);
InBlock.gif    
public abstract bool DeleteUser (string username,
InBlock.gif        
bool deleteAllRelatedData);
InBlock.gif    
public abstract MembershipUserCollection GetAllUsers
InBlock.gif        (
int pageIndex, int pageSize, out int totalRecords);
InBlock.gif    
public abstract int GetNumberOfUsersOnline ();
InBlock.gif    
public abstract MembershipUserCollection FindUsersByName
InBlock.gif        (
string usernameToMatch, int pageIndex, int pageSize,
InBlock.gif        
out int totalRecords);
InBlock.gif    
public abstract MembershipUserCollection FindUsersByEmail
InBlock.gif        (
string emailToMatch, int pageIndex, int pageSize,
InBlock.gif        
out int totalRecords);
InBlock.gif    
// Virtual methods
InBlock.gif
    protected virtual byte[] EncryptPassword (byte[] password);
InBlock.gif    
protected virtual byte[] DecryptPassword (byte[] encodedPassword);
InBlock.gif    
protected virtual void OnValidatingPassword
InBlock.gif        (ValidatePasswordEventArgs e);
InBlock.gif    
// Events
InBlock.gif
    public event MembershipValidatePasswordEventHandler
InBlock.gif        ValidatingPassword;
ExpandedBlockEnd.gif}

None.gif

 

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框架里包含的是有区别的,主要是为了能让提供的源代码能让用户独立的编译和运行。
今天这篇文章写的太长,自己都有点晕了,有错误的地方多包涵。

顶

转载于:https://www.cnblogs.com/dotLive/archive/2006/07/27/461243.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么要保持软件包依赖项自由循环的五个原因

如果您很不幸不能在一个项目中与我一起工作&#xff0c;那么您将遭受所有软件包依赖项必须无循环的规则的困扰。 我不仅需要这样做 &#xff0c;而且还将创建一个单元测试&#xff0c;以确保使用Degraph进行测试。 这就是我认为无周期封装结构对项目有益的原因。 有用的抽象 &…

Servlet技术

----Servlet是用Java语言编写的应用到Web服务器端的扩展技术&#xff0c;它先于jsp产生&#xff0c;可以方便地对Web应用中的HTTP请求进行处理。在Java Web程序开发中&#xff0c;Servlet主要用于处理各种业务逻辑&#xff0c;他比jsp更具有业务逻辑层的意义。 一。Servlet基础…

Mysql远程登录及常用命令

第一招&#xff1a;mysql服务的启动和停止 启动&#xff1a;net start mysql 停止&#xff1a;net stop mysql 第二招&#xff1a;登陆mysql 语法如下&#xff1a;mysql -u用户名 -p用密码 键入命令mysql -uroot -p&#xff0c;回车后提示你输入密码&#xff0c;输入12345&…

基于Spring Boot的WebSocket应用程序并捕获HTTP会话ID

我最近参与了一个项目&#xff0c;我们需要捕获Websocket请求的http会话ID –原因是要确定使用相同基础HTTP会话的Websocket会话的数量。 这样做的方法基于利用新的spring-session模块的示例&#xff0c;并在此处进行描述。 捕获http会话ID的技巧是理解在浏览器和服务器之间建…

用过的jQuery记录

var list $(input:radio[name"name"]:checked).val();  //选择input中单选name为“name”的并且是选中状态的 index $(document).data(index);  //把参数存入document中保存起来并在下一次中取出再用index 1index $(document).data(index); str.find("input…

windows phone画板程序

前几天想要这样一个程序&#xff0c;没找到&#xff0c;今天上网偶然发现了&#xff0c;转载过来。 <Grid> <InkPresenter x:Name"MyPresenter" HorizontalAlignment"Left" VerticalAlignment"Top" MouseLeftButtonDown"MyP…

文件指针创建失败!File *fp失败

问题记录&#xff1a;项目是在所里边的vs2010上创建的&#xff0c;正常&#xff01;在自己的笔记本上使用vs13和19都一直报错&#xff01;指针一直为空&#xff01; 网上查了好久&#xff0c;试了很多方法都没有用&#xff01;最后发现是权限的问题&#xff0c;c盘下边创建不了…

前端开发:小程序--第一步

当我在接到小程序的项目的时候&#xff0c;几乎可以说是一脸懵因为对小程序的概念说实话是不太理解的&#xff0c;或者说理解的不太透彻&#xff0c;但是领导给项目说要完成&#xff0c;那没办法&#xff0c;还是要继续呀。 首先&#xff0c;我就想着先注册一个看看&#xff0…

但这是不可能的,或者无法发现JIT破坏了您的代码。

时不时地查看一些代码&#xff0c;并认为它不可能是错误的。 一旦您排除了简单的程序员搞砸代码/代码中的敌对行为&#xff08;确保您阅读Java Puzzlers或类似内容&#xff09;或并发问题&#xff08;阅读Java Concurrency或继续学习Heniz博士的出色课程 &#xff09;&#xff…

【解决】insert 语句无效果,在查询中正常运行问题

今天碰到一个奇怪的问题&#xff0c;具体见csdn&#xff1a;http://topic.csdn.net/u/20120424/19/0aeacbce-a9d5-4630-8b87-a08d5df1828b.html?seed1347097422&r78358698#r_78358698 解决方法与原因:猜测&#xff0c; 因为数据库是我再vs2010中建立的&#xff0c;数据库版…

最近开始研究和关注的技术

留个草稿&#xff0c;慢慢补充。 Acropolis&#xff0c;基于WPF的应用程序框架&#xff0c;某种角度可以认为是CAB的WPF实现&#xff1b; http://windowsclient.net/acropolis/&#xff0c;Cider似乎还是不完善......不知道VS2008 Release时能不能妥善处理好WPF在设计期的渲染。…

html行级元素和块级元素以及css转换

之前有说过html的标签是有语义的&#xff0c;当然也就有一些默认的样式&#xff0c;比如标题有h1h6&#xff0c;他们的字体由大至小一次递减&#xff0c;字体比一般字体要加粗。 这样也就有了行级元素和块级元素&#xff0c;下面来看看什么是行级元素什么事块级元素&#xff1…

EasyCriteria已演变为uaiCriteria。 新名称和更多功能

你好&#xff01;你好吗&#xff1f; 我很高兴宣布uaiCriteria的发布&#xff0c;EasyCriteria的演进。 确实需要更改框架名称吗&#xff1f; 是的&#xff0c;可悲的是。 我找到了另一个具有相同名称的框架 &#xff0c;这就是为什么我决定更改名称的原因&#xff08;我不希…

ajax方式下载文件

在web项目中需要下载文件&#xff0c;由于传递的参数比较多&#xff08;通过参数在服务器端动态下载指定文件&#xff09;&#xff0c;所以希望使用post方式传递参数。通常&#xff0c;在web前端需要下载文件&#xff0c;都是通过指定<a>标签的href属性&#xff0c;访问服…

了解Spring Web应用程序体系结构:经典方法

每个开发人员必须了解两件事&#xff1a; 架构设计是必要的。 花哨的体系结构图没有描述应用程序的真实体系结构。 真正的体系结构是从开发人员编写的代码中找到的&#xff0c;如果不设计应用程序的体系结构&#xff0c;最终将得到一个具有多个体系结构的应用程序。 这是否…

使用unicode

#include <iostream> class 我的类 { public:我的类(int 我的初始化变量){我的成员变量 我的初始化变量;}~我的类(){}int 我的成员变量;void 打印我的变量(){std::cout<<我的成员变量<<std::endl;}; };int main() {我的类 我的实例(1);我的实例.打印我的变量…

springmvc注解小示例(转)

转自&#xff1a;http://www.blogjava.net/pengo/archive/2010/11/28/339229.html 弃用了struts&#xff0c;用spring mvc框架做了几个项目&#xff0c;感觉都不错&#xff0c;而且使用了注解方式&#xff0c;可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mv…

解决maven项目Cannot change version of project facet Dynamic web module to 3.0

1、打开新建的servlet文件例如&#xff08;hibernate.cfg.xml&#xff09;修改头文件为 <?xml version"1.0" encoding"UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" &quo…

使用Forge插件在现有Java EE项目上启用Arquillian

技术提示&#xff03;34解释了如何创建可测试的Java EE 7应用程序。 如果要启动新的应用程序&#xff0c;这将很有用。 但是&#xff0c;如果您已经有一个应用程序并启用Arquillian怎么办&#xff1f; 这就是Forge和Forge-Arquillian附加组件派上用场的地方。 这就是我在javae…

HDOJ1166 敌兵布阵【线段树】

Problem : 1166 ( 敌兵布阵 ) Judge Status : AcceptedRunId : 5862942 Language : GCC Author : qq1203456195 #include <stdio.h> #define lson l,m,rt<<1 #define rson m1,r,rt<<1|1 #define maxn 55555 int sum[maxn<<2]; void PushUp(i…