如何通过 SimpleMembership 和 WebSecurity 使用我自己的数据库?什么是 MVC4 安全性? [英] How do I use my own database with SimpleMembership and WebSecurity? What is MVC4 security all about?
问题描述
我已经阅读了我能找到的关于这个主题的所有内容,包括 MSDN 文章和 SO 帖子,但我仍然非常迷茫和困惑.
I've read everything on this topic I could find, including MSDN articles and SO posts, but I'm still very lost and confused.
请回答以下问题(如果可能,请简要回答):
Please answer the following (briefly, if possible):
什么是SimpleMembership/SimpleMembershipProvider (WebMatrix.WebData) 以及它/他们负责什么?
What is SimpleMembership/SimpleMembershipProvider (WebMatrix.WebData) and what is it/are they responsible for?
什么是WebSecurity (WebMatrix.WebData)?
什么是Membership (System.Web.Security) 类?
为什么 MVC4 会创建一个 UserProfile 表和一个 webpages_Membership 表?它们是做什么用的,有什么区别?MVC4 创建的 UserProfile 类是什么?
Why does MVC4 create a UserProfile table and a webpages_Membership table? What are they for and what is the difference? What is the UserProfile class that MVC4 creates?
什么是 UsersContext 类?
所有这些如何协同工作以进行用户身份验证?
How do all of these work together to make user authentication?
我的情况
这些问题会引出下一个问题:
My Situation
These questions then lead into the next problem:
假设我有一个包含用户(ID、用户名、密码)的现有数据库.我正在创建一个新的 MVC4 应用程序并使用表单身份验证.用户密码以加密形式(不是 bcrypt)存储在数据库中.
Suppose I have an existing database with users (IDs, Usernames, passwords). I'm creating a new MVC4 application and using Forms Authentication. User passwords are stored in the database in an encrypted form (not bcrypt).
我需要做什么才能使其与 MVC4 一起工作?
What do I have to do to make it work with MVC4?
我是否必须创建一个自定义的MembershipProvider?
Do I have to create a custom MembershipProvider?
据我所知,WebSecurity 是一个与 MembershipProvider 交互的静态类(模块).MembershipProvider 是一个解释特定函数如何工作的类,例如 ValidateUser、CreateUser、ChangePassword.
As far as I can understand, WebSecurity is a static class (Module) that interacts with a MembershipProvider. A MembershipProvider is a class that explains how particular functions work, such as ValidateUser, CreateUser, ChangePassword.
为了解决我的问题,我假设我需要创建一个自定义 MembershipProvider 并告诉 WebSecurity 使用我的新 MembershipProvider.
To solve my problem I assume I need to create a custom MembershipProvider and tell WebSecurity to use my new MembershipProvider.
我已经悬赏这个问题并打算将其奖励给 Andy Brown 的杰出回答.
I have placed a bounty on this question and intend to award it to Andy Brown for an outstanding answer.
推荐答案
请参阅每条引文下方的摘要以获取快速答案,并查看段落以获取详细信息.另请参阅最后的参考资料部分以获取权威来源.
1.什么是 SimpleMembership/SimpleMembershipProvider (WebMatrix.WebData) 以及它/它们负责什么?
1.What is SimpleMembership/SimpleMembershipProvider (WebMatrix.WebData) and what is it/are they responsible for?
SimpleMembership(该术语涵盖 SimpleMembershipProvider
和 SimpleRoleProvider
) 负责提供一种干净、快捷的方式来实现 80% 的即插即用身份验证和授权框架,并带有安全密码存储,任何人都可以使用.
SimpleMembership (a term that covers both the SimpleMembershipProvider
and SimpleRoleProvider
) is responsible for providing a clean and quick way of implementing an 80 %-there plug and play authentication and authorisation framework with secure password storage, that anyone can use.
2.什么是网络安全(WebMatrix.WebData)?
2.What is WebSecurity (WebMatrix.WebData)?
网络安全
是一个用于常见会员任务的辅助类,它与 Membership
和 OAuthWebSecurity
.角色仍然通过 Roles
.
3.Membership (System.Web.Security) 类是什么?
3.What is the Membership (System.Web.Security) class?
会员资格
是来自原始 ASP.NET 成员资格实现的静态类,用于管理用户设置和操作.许多用户操作仍然在这里完成,而不是在 WebSecurity
中重复.他们都使用您选择的同一个提供商.
Membership
is a static class from the original ASP.NET membership implementation that manages user settings and operations. Many user operations are still done here rather than repeating them in WebSecurity
. They both use the same provider of your choice.
4.MVC4 为什么要创建一个 UserProfile 表和一个 pages_Membership 表?它们是做什么用的,有什么区别?MVC4 创建的 UserProfile 类是什么?
4.Why does MVC4 create a UserProfile table and a webpages_Membership table? What are they for and what is the difference? What is the UserProfile class that MVC4 creates?
这两个表执行不同的功能.webpages_Membership
架构由框架控制并用于凭据,UserProfile
架构由我们控制并用于我们要针对用户存储的任何属性.
The two tables perform different functions. The webpages_Membership
schema is controlled by the framework and used for credentials, the UserProfile
schema is controlled by us and used for any properties we want to store against a user.
5.UsersContext 类是什么?
5.What is the UsersContext class?
这是一个 DbContext
(DbContext API 的一部分) 作为 MVC Internet 应用程序模板的启动提供.它唯一的工作是包含 UserProfile
类,以便我们可以使用它(例如,通过 InitializeSimpleMembershipAttribute
).
It is a DbContext
(part of the DbContext API) provided as a starting by the MVC Internet Application template. Its only job is to contain the UserProfile
class so we can work with it (e.g. through InitializeSimpleMembershipAttribute
).
6.所有这些如何协同工作以进行用户身份验证?
6.How do all of these work together to make user authentication?
现在从上面的摘要和下面的细节中应该可以明显看出这一点.使用:WebSecurity
用于常见任务;UserProfile
用于针对用户存储的自定义属性,通过 UsersContext
(在 Visual StudioMVC Internet 应用程序"模板中)访问;Membership
当 WebSecurity
或 OAuthWebSecurity
没有方法时;和 Roles
用于角色.使用VS模板的控制器查看使用示例.
This should now be evident from the summaries above and the detail below. Use: WebSecurity
for common tasks; UserProfile
for custom properties to store against a user, accessed through the UsersContext
(in the Visual Studio "MVC Internet Application" template); Membership
when WebSecurity
or OAuthWebSecurity
doesn't have the method; and Roles
for roles. Use the VS template's controller to see examples of use.
编辑.万一有人走到这一步
假设我有一个现有的数据库......
Suppose I have an existing database ...
如果您有一个现有的数据库,并且您编写自定义成员资格提供程序的唯一原因是处理您的旧密码存储方法,那么您可以使用一种解决方法.只有当您可以从旧密码存储转移到 SimpleMembership 算法(使用 Rfc2898DeriveBytes
类).详情见脚注.
If you have an existing database, and your only reason for writing a custom membership provider is to deal with your legacy password storage method, then you could use a workaround. This will only work if you can move away from your old password storage to the SimpleMembership algorithm (which uses the Rfc2898DeriveBytes
class). See the footnote for details.
如果你不能离开,那么是的,你将不得不创建你自己的提供者来使用你的特定密码算法,你可以这样做来自SimpleMembershipProvider
.
If you can't move away, then yes you are going to have to create your own provider to use your specific password algorithm, which you can do by deriving from SimpleMembershipProvider
.
注意:SimpleMembershipProvider
将散列您的密码而不是加密它们.如果您不知道区别以及为什么这很重要,那么在使用自定义安全性为您自己的提供程序提供服务之前请三思
NOTE: SimpleMembershipProvider
will HASH your passwords not ENCRYPT them. If you don't know the difference and why that is important then think twice before doing your own provider with custom security
要了解这一切如何组合在一起,有助于了解历史.
To understand how it all fits together it helps to understand the history.
- ASP.NET 在 2005 年 引入了 ASP.NET 会员系统
- 该系统使用提供者从用于管理帐户和角色等的通用接口中抽象出实现细节.
- 它还为我们提供了基本的用户配置文件"功能(存储在人们倾向于避免的单列 xml 字段中)
- SimpleMembership 于 2010 年发布,作为插入 ASP.NET 会员系统的提供程序,但也允许 OAuth 身份验证和每列用户配置文件存储(而不是使用的单列存储)在原始实现中).
SimpleMembershipProvider
实现ExtendedMembershipProvider
扩展原始提供者实现
它是开源的 on codeplex(镜像 在 github 上).就安全而言,您可以自己评估代码、克隆它、更改它等.您应该使用 您自己的观点关于优点和缺点 开源安全性,并用一点NIH 来解决这个问题.(个人观点:我有时用,其他时候不用)
It is Open Source on codeplex (mirrored on github). As far as security goes you can therefore assess the code yourself, clone it, change it etc. You should take your own view on the benefits and drawbacks of open source security, and cook that up up with a pinch of NIH. (Personal view: I use it sometimes, I don't use it other times)
ExtendedMembershipProvider
本身将诸如 GeneratePasswordResetToken
之类的命令添加到旧的会员提供程序 api.
ExtendedMembershipProvider
in itself adds commands like GeneratePasswordResetToken
to the old membership provider apis.
网络安全
只是一个外观或辅助类,用于提供对 SimpleMembershipProvider
的简单访问,并使常见任务在一个地方变得容易和可访问.它可以提供帮助,因为通过 ExtendedMembershipProvider
对原始框架的扩展意味着像 Membership
这样的一些原始类现在已经不够用了.示例:
WebSecurity
is simply a facade, or helper class, to provide simple access to SimpleMembershipProvider
and make common tasks easy and accessible in one place. It is there both to help and because the extension of the original framework through ExtendedMembershipProvider
means some of the original classes like Membership
aren't enough now. Examples:
WebSecurity.CurrentUserName
- 获取当前登录用户的名称WebSecurity.CreateUserAndAccount
.同时创建用户并设置用户配置文件属性(例如WebSecurity.CreateUserAndAccount(userName, pw, new { Email = model.Email });
WebSecurity.InitializeDatabaseConnection
- 快速设置一个新的/现有的数据库以供会员使用,选择您的用户 ID 列和用户自然密钥标识符等.ResetPassword
重置用户密码,GeneratePasswordResetToken
等等
WebSecurity.CurrentUserName
- gets the name of the currently logged in userWebSecurity.CreateUserAndAccount
. Simultaneously create a user and set user profile properties (e.g.WebSecurity.CreateUserAndAccount(userName, pw, new { Email = model.Email });
WebSecurity.InitializeDatabaseConnection
- Quickly setup a new/existing database for use with membership, choose your user id column and user natural key identifier etc.ResetPassword
to reset a user password,GeneratePasswordResetToken
and many more
这些方法通常依赖于您正在使用的提供者,它们不仅仅依赖于 SimpleMembership,而且它们将像您的提供者和 Membership
这样的对象联系在一起,以提供一个共同点做成员函数.
These methods generally defer to the provider you are using, they don't just depend on SimpleMembership, and they tie together objects like your provider and Membership
to provide a common point to do membership functions.
请注意,还有 OAuthWebSecurity
相当于用于 OAuth 身份验证的 WebSecurity
.
Membership
来自原始实现;它使用基本的 MembershipProvider
实现管理用户设置并执行与用户相关的操作,ExtendedMembershipProvider
现在扩展了该实现.它是一个静态类,因此在您声明命名空间的任何地方都可用,因此是一种简单的方法,例如,检索当前用户:Membership.GetUser
Membership
is from the original implementation; it manages user settings and performs user-related operations using the basic MembershipProvider
implementation which ExtendedMembershipProvider
now extends. It is a static class, so is available anywhere you declare the namespace, and is therefore an easy way to, for example, retrieve the current user: Membership.GetUser
WebSecurity
做了一些事情而不是其他事情,而 Membership
做了一些事情而不是其他事情,这引起了混淆.如果您将 WebSecurity
视为用于更高级别操作的工具包,而将 Membership
视为对用户执行操作的工具包,那么您会没事的;他们一起为您的提供商工作.
There is confusion caused by the fact that WebSecurity
does some things and not others, and Membership
does some things and not others. If you view WebSecurity
as a toolkit for higher level operations, and Membership
as a toolkit to do things to a user, you'll be ok; they work together on your provider.
webpages_Membership
是一个具有固定架构的表,我们不理会它,它允许提供者进行基本的帐户操作,主要是存储凭据.UserProfile
是我们自定义的一个表,用于存储用户帐户的信息,并通过UserProfile
类以强类型格式提供该表.- 有一个名为
webpages_OAuthMembership
的额外表,它与webpages_Membership
执行相同的工作,但适用于您想要集成的 OAuth 登录提供程序.
webpages_Membership
is a table with a fixed schema that we leave alone, and allows the provider to do the basic account operations, mainly storing credentials.UserProfile
is a table that we customise to store information against a user account, and have that made available in a strongly typed format through theUserProfile
class.- There is an extra table called
webpages_OAuthMembership
which does the same job aswebpages_Membership
, but for OAuth login providers that you want to integrate with.
此设置的神奇之处在于,单个用户可以在您自己的网站上拥有会员登录名,并且可以使用不同的提供商(如 google、facebook)进行任意数量的 OAuth 登录,并且它们都共享存储在 UserProfile 中的通用配置文件
The magic of this setup is that a single user can have a membership login on your own site, and any number of OAuth logins with different providers like google, facebook, and they all share a common profile stored in UserProfile
通常,如果表以 webpages_
开头,则表示有 API 可以访问它.UserProfile
表由 UsersContext
中的 UserProfile
类表示(如果您使用默认的 MVC Internet 应用程序模板).因此,我们通过与 DbContext
中包含的任何类一起使用的常用方法来访问它.
Generally if a table starts with webpages_
, it means there is an API to access it. The UserProfile
table is represented by the UserProfile
class in your UsersContext
(if you use the default MVC Internet Application template). Therefore we access this through the usual methods we would use with any class contained in a DbContext
.
UserProfile
对代码优先非常友好:您可以添加列(如用户的 Email
地址),然后设置迁移以将该列包含在您的数据库中在您的下一个版本中(如果您喜欢使用迁移).实际上,不必调用 UserProfile
表 - 您可以使用 WebSecurity.InitializeDatabaseConnection
调用来更改它,[Table("UserProfile")]公共类 UserProfile
,以及您自己的迁移.
UserProfile
is very code-first friendly: you can add columns (like the user's Email
address), and then set up a migration to include that column in your database on your next release (if you like using migrations). In fact, the UserProfile
table does not have to be called that - you can change that using the WebSecurity.InitializeDatabaseConnection
call, [Table("UserProfile")] public class UserProfile
, and your own migrations.
这是来自 Visual Studio 新项目中提供的 MVC Internet 应用程序模板.我做的第一件事是确保它与我自己的数据库上下文共享一个公共连接字符串(假设成员资格表在同一个数据库中).如果需要,您可以更改此设置并稍后将它们分离.
This is from the MVC Internet Application template provided in Visual Studio New Project. The first thing I do is make sure that it shares a common connection string with my own database context (assuming the membership tables are in the same database). You can change this and decouple them later if you want.
您不需要将它与您自己的上下文分开 - 只有当您现在或将来想将会员信息存储在不同的数据库中时才需要这样做如果您摆脱它,您只需更改对 UsersContext
到您自己的上下文,调整 Database.SetInitializer
.
You don't need to have it separate to your own context - that is only necessary if you want to store membership information in a different database now or in the future If you get rid of it you can just change references to UsersContext
to your own context, adjusting Database.SetInitializer
.
参考:
在 ASP.NET 网页中使用 SimpleMembership -马修·奥斯本- 这是关于 SimpleMembership 的原始参考资料,以及它是什么、为什么会出现以及它的作用:
Using SimpleMembership With ASP.NET WebPages - Matthew Osborn - This is the original reference about SimpleMembership and what it is, why it is, and what it does:
MSDN - 会员简介- 会员资格仍然是 SimpleMembership 的核心,因此了解一下它会有所帮助.
MSDN - Introduction to Membership - Membership is still at the core of SimpleMembership, so it helps to understand a bit about it.
- codeplex 源(镜像 在 github 上).
网络安全
OAuthWebSecurity
SimpleMembershipProvider
ExtendedMembershipProvider
SimpleRoleProvider
会员资格
一个>角色
一个>DbContext
和 DbContext API
- codeplex source (mirrored on github).
WebSecurity
OAuthWebSecurity
SimpleMembershipProvider
ExtendedMembershipProvider
SimpleRoleProvider
Membership
Roles
DbContext
and the DbContext API
编辑脚注:执行滚动密码升级的详细信息
EDIT Footnote: the detail for doing a rolling password upgrade
- 向
UserProfile
添加一个属性,用于存储帐户所在的密码版本(例如,1 表示旧版,2 表示 SimpleMembership) - 在登录"操作中,编写代码以便:
- 如果它们使用的是您的 SimpleMembership 密码版本,则您可以正常登录
- 如果他们使用旧密码版本,您:
- 使用旧方法检查
- 如果您使用
ResetPassword
重置它是正确的,然后使用ChangePassword
以使用 SimpleMembership 版本,这会将字段更新为新密码版本 - 最后更新
UserProfile
上的密码版本
- Add a property to
UserProfile
which stores what password version the account is on (e.g. 1 for legacy, 2 for SimpleMembership) - In the "Login" Action, write code so that:
- If they are on your SimpleMembership password version, you do a normal login
- If they are on the legacy password version, you:
- check it using your old method
- if it is correct you reset it using
ResetPassword
thenChangePassword
to use the SimpleMembership version, this will update the field to the new password version - and finally update the Password version on the
UserProfile
使用
可以使所有这些都具有事务性交易范围
.唯一令人讨厌的是控制器中的额外代码,以及与webpages_Membership
的耦合.这篇关于如何通过 SimpleMembership 和 WebSecurity 使用我自己的数据库?什么是 MVC4 安全性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!