理解和使用 ASP.NET MVC 4.0 中的 Simple Membership Provider






4.62/5 (35投票s)
在本文中,我们将探讨 ASP.NET Simple Membership Provider,它是 ASP.NET MVC 4 互联网应用程序默认的身份验证和授权机制。
引言
在本文中,我们将探讨 ASP.NET Simple Membership Provider,它是 ASP.NET MVC 4 互联网应用程序模板中默认的身份验证和授权机制。我们将尝试理解 Simple Membership Provider,并将其与 ASP.NET 角色和成员资格提供程序 API 进行比较。
背景
让我们从了解什么是身份验证和授权开始。身份验证意味着验证用户。在此步骤中,我们验证用户凭据以检查尝试登录的人是否是正确的。另一方面,授权是跟踪当前用户允许查看的内容以及应向其隐藏的内容。它更像是一个注册表,用于记录向用户显示什么以及不显示什么。
每当用户登录时,他都必须使用其凭据进行身份验证。一旦通过身份验证,他将被授权查看网站的资源/页面。这两个概念通常是同步进行的。
随着 ASP.NET 2.0 的发布,ASP.NET 框架中引入了角色和成员资格 API,它提供了解决身份验证和授权问题所需的所有样板代码和数据库架构。实现身份验证和授权只需插入 ASP.NET 成员资格 API,成员资格提供程序就为我们提供了开箱即用的身份验证和授权功能。要了解更多信息,请参阅:理解 ASP.NET 角色和成员资格 - 初学者教程[^]
在 ASP.NET 成员资格提供程序 API 中,用户和角色表中的信息是预定义的,无法自定义。用户配置文件信息也存储在同一个数据库中。使用 ASP.NET 成员资格提供程序完全控制数据库并不容易和直接。因此,一些应用程序仍然需要使用自己的数据库来实现其身份验证和授权机制,以跟踪用户及其角色。出现此类要求的一些原因可能是:
- 我们有一个现有数据库,并且正在尝试使用它实现一个应用程序。
- 角色和成员资格功能对于我们的应用程序来说是多余的。
- 角色和成员资格功能不足以满足我们的应用程序需求,我们需要自定义数据。
可以使用带有 ASP.NET 的自定义身份验证和授权机制。这种技术被称为自定义表单身份验证机制。要了解有关自定义表单身份验证的更多信息,请参阅
随着 ASP.NET MVC 4 的发布,微软提供了 Simple Membership Provider API。与 ASP.NET 成员资格提供程序相比,Simple Membership API 的主要优势是更简单、更成熟,并且相对更容易完全控制。Simple Membership Provider 的另一个主要优势是它对持久性是无知的。这意味着它为我们提供了一组模型来完成身份验证和授权,并使用了代码优先的方法。应用程序开发人员可以决定这些模型应该在何处以及如何持久化(由 Entity Framework Code First 支持)。
使用代码
让我们尝试创建一个简单的 ASP.NET MVC4 互联网应用程序,并观察 Simple Membership Provider 的运行。当我们创建 ASP.NET MVC 4 互联网应用程序模板时,项目结构将如下所示:
模板提供了一个用于 UserProfile
的模型和一个用于处理此模型的 UsersContext
类。(Models/AccountModels.cs)
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet UserProfiles { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
此用户模型仅带有一个字段,即用户名,但我们可以在此模型中为用户配置文件添加任意数量的字段。
下一个重要的事情是查看 InitializeSimpleMembershipAttribute
属性(Filters/InitializeSimpleMembershipAttribute.cs)。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
此属性的作用是负责初始化 Simple Membership Provider,指定应用于执行数据库操作的上下文类,即 UsersContext。WebSecurity.InitializeDatabaseConnection
方法将用于指定数据库,使用连接字符串(在本例中为 "DefaultConnection
"),应用于获取用户配置文件信息的模型(在本例中为 "UserProfile
"),以及应用于登录的字段(在本例中为 "UserName
")。
现在,此属性将创建一个成员资格数据库,其位置在连接字符串中指定。它将为我们的 UserProfile
模型创建表,其中包含 UserProfile
类中指定的所有属性的列。它将使用 UserId
字段来维护与自动生成的表的外键关系,并将使用 UserName
字段作为登录所需的字段。然后它将创建身份验证和授权所需的一些表。
接下来要注意的是 AccountController
。我不会在这里讨论完整的类,但此类的所有 CRUD 操作都包装在“注册”、“登录”、“管理”功能中。需要注意的重要一点是与控制器关联的 InitializeSimpleMembership
。因此,无论用户何时尝试登录/注册,Simple Membership 都会自动初始化。
[InitializeSimpleMembership]
public class AccountController : Controller
{
}
此外,此类还包含一些用于外部登录的代码,我将稍后解释。首先,让我们尝试查看 Simple Membership Provider 创建的数据库。要查看表,让我们修改连接字符串以指向 App_data
文件夹并创建一个示例数据库。
< add name="DefaultConnection" connectionString="data source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\sampleDb.mdf;integrated security=True;user instance=True;multipleactiveresultsets=True;" providerName="System.Data.SqlClient" />
现在让我们运行应用程序并单击“注册”。这将调用 AccountController
,后者将依次调用 InitializeSimpleMembership
构造函数,并创建 Simple Membership 数据库以及我们的 UserProfile
模型所需的 UserProfile
表。现在让我们看看已创建的表。
现在这张图片中,我们可以看到为我们的模型创建的 UserProfile
表。Simple Membership Provider 也创建了一个表。
-
webpages_Membership
:此表将跟踪用户的登录凭据哈希、盐和恢复信息。 -
webpages_Roles
:此表将跟踪系统中的所有角色。 -
webpages_UserInRoles
:此表将维护我们的用户配置文件表和角色表之间的多对多关系。 -
webpages_OAuthMemebrship
:如果任何用户选择使用开放身份验证,则应用程序将不包含登录凭据的任何信息,而我们只包含开放身份验证提供程序和用户 ID 的信息。此表将跟踪使用开放身份验证登录应用程序的用户。
默认模板还附带了视图,允许我们执行基本的登录、注册和用户管理。现在,使用此 Simple Membership Provider,如果我们需要在用户配置文件中包含自定义字段,只需将它们添加到我们的用户配置文件模型中即可。身份验证和授权相关的表与用户配置文件表是分开的。
与 ASP.NET 成员资格 API 相比,唯一的限制是无法使用 WSAT
工具来处理 Simple Membership Provider 的角色和用户-角色功能,但这可以通过创建一个简单的页面来管理角色和用户-角色分配轻松实现。
值得关注的点:
Simple Membership Provider 使那些需要开发自定义表单身份验证的应用程序更容易实现身份验证和授权。这更像是一篇理论性文章,但我相信那些正在进行自定义表单身份验证的开发人员会发现 Simple Membership Provider 非常有用。我希望这篇文章对您有所帮助。
历史
- 2013 年 11 月 29 日:第一版