我应该如何在ASP.Net MVC站点中进行身份验证?

时间:2021-06-04 03:13:38

I have a site which has an area that requires authentication. Right now I use the roles attribute on all the controllers in that area, and I run a query to retrieve that users ID, and all their settings.

我的网站有一个需要身份验证的区域。现在我在该区域的所有控制器上使用roles属性,并运行查询以检索该用户ID及其所有设置。

It seems like a code or design smell to me that I am retrieving the userid and settings each time a controller in that area loads up? I'm not sure if I should be using sessions, or if ASP.Net MVC 2.0 provides some unique way to handle this. Another concern is security.

对我来说,似乎是一个代码或设计气味,我每次在该区域的控制器加载时检索用户ID和设置?我不确定我是否应该使用会话,或者ASP.Net MVC 2.0是否提供了一些独特的方法来处理这个问题。另一个问题是安全性。

Overall, I don't really know which way to turn. Design wise I would like the userId and settings retrieved only once when the user logs into the area. Right now I grab the userId each time a controller loads up, and then if required, I query the database for their settings each time as well.

总的来说,我真的不知道转向哪种方式。设计明智我想在用户登录该区域时只检索一次userId和设置。现在我每次控制器加载时都会抓取userId,然后如果需要,我每次都会查询数据库的设置。

6 个解决方案

#1


11  

One of the rules about security is that you shouldn't try to do it yourself. There are many pitfalls in doing an authentication system correctly without leaving loopholes or backdoors. Thus, in that regard, you might consider the SqlMembershipProvider that comes with .NET. It can be used with MVC and provides the means to get roles and the current security context, is easy to setup and configure and will be more secure than rolling your own.

关于安全性的规则之一是你不应该自己尝试。在不留下漏洞或后门的情况下正确地进行身份验证系统存在许多缺陷。因此,在这方面,您可能会考虑.NET附带的SqlMembershipProvider。它可以与MVC一起使用,并提供获取角色和当前安全上下文的方法,易于设置和配置,并且比滚动自己更安全。

If you are not using SQL Server, you have a couple of choices. One solution would be to use something like SQL Server Express or SQL Server Compact Edition to maintain the credentials. Another solution would be to mimic the SqlMembrershipProvider database schema and then write a custom provider that communicates with that schema.

如果您不使用SQL Server,则有几个选择。一种解决方案是使用SQL Server Express或SQL Server Compact Edition之类的东西来维护凭据。另一种解决方案是模仿SqlMembrershipProvider数据库模式,然后编写与该模式通信的自定义提供程序。

The last choice would be to write a custom MembershipProvider class. While this is still rolling your own, it forces you into the structure of the MembershipProvider so that you can swap it out at a later date for a different one (e.g. ActiveDirectoryMembershipProvider) and provides a common interface for interacting with credentials and logins which for example enables easy use of the built-in Login control.

最后一个选择是编写自定义MembershipProvider类。虽然这仍然是您自己的,但它会强制您进入MembershipProvider的结构,以便您可以在以后将其交换为另一个(例如ActiveDirectoryMembershipProvider),并提供用于与凭证和登录进行交互的通用接口,例如可以轻松使用内置的Login控件。

If you are already using a MembershipProvider and are asking about storing additional user-specific data, then I would suggest the SqlProfileProvider with all the caveats I mentioned above about the SqlMembershipProvider. the ProfileProvider provides a structure for maintain user-specific data with the currently logged on user.

如果您已经在使用MembershipProvider并且询问存储其他特定于用户的数据,那么我建议SqlProfileProvider包含我上面提到的关于SqlMembershipProvider的所有警告。 ProfileProvider提供了一个结构,用于维护当前登录用户的用户特定数据。

For more information:

了解更多信息:

#2


1  

You could also implement a custom identity. They are very easy to implement, and they let you store whatever user information you want in Identity, which is then stored in the cookies that Identity puts down, so you're not hitting the DB every time to get that info.

您还可以实现自定义标识。它们非常容易实现,它们允许您在Identity中存储您想要的任何用户信息,然后将其存储在Identity放下的cookie中,这样您每次都不会访问数据库以获取该信息。

Just create a new class that inherits from GenericIdentity, and you'll be on your way.

只需创建一个继承自GenericIdentity的新类,您就可以了。

You of course have to be careful how much info you put there since it's in a cookie, but usually user related information in the case you're talking about here isn't so big.

你当然要小心你放在那里有多少信息,因为它在一个cookie中,但是你在这里讨论的情况下通常与用户相关的信息并不是那么大。

We use a custom identity to store a few bits of info about the user, and it works out pretty well.

我们使用自定义标识来存储有关用户的一些信息,并且效果非常好。

#3


0  

You could store an object in session that holds all the required user information. You will just need to add a property in the Controllers, Views or other base classes where you want to retrieve the user information/profile. This would be the authorisation info as opposed to any authentication info (eg Forms authentication)

您可以在会话中存储包含所有必需用户信息的对象。您只需要在控制器,视图或其他要检索用户信息/配置文件的基类中添加属性。这将是授权信息,而不是任何身份验证信息(例如,表单身份验证)

#4


0  

You might try "Windows Identity Foundation". I've been using it on one of my projects for a while. It allows for "claims-based authentication", which basically means that you get to designate "claims", strings of information that describe the user when she logs on.

您可以尝试“Windows Identity Foundation”。我已经在我的一个项目上使用它了一段时间。它允许“基于声明的身份验证”,这基本上意味着您可以指定“声明”,即在用户登录时描述用户的信息串。

Once logged on, the user's claims can be read from the HttpContext.Current.User field. You can also use "Role" claims that seamlessly integrate with a role-based authentication schema; meaning that you can give the user a "manager" role claim and then use `if (User.IsInRole("manager")).

登录后,可以从HttpContext.Current.User字段中读取用户的声明。您还可以使用与基于角色的身份验证架构无缝集成的“角色”声明;意思是你可以给用户一个“经理”角色声明,然后使用`if(User.IsInRole(“manager”))。

As an added bonus, WIF makes it very easy to re-use your login screen in other applications.

作为一个额外的好处,WIF可以很容易地在其他应用程序中重用您的登录屏幕。

All in all, it's very flexible, but the documentation is very poor. I've asked and answered a number of questions about "Windows Identity Foundation" on *.

总而言之,它非常灵活,但文档非常差。我已经在*上询问并回答了一些关于“Windows Identity Foundation”的问题。

#5


0  

We have done this quite a few times in the past. Similar to what Thomas mentions, what we have generally done is implemented a new Membership provider based on the Microsoft SQL Memberhsip provider to do this. We inherit from the base MembershipUser class and add any custom properties we would want to have on the user object. You have to implement a database read for the Membership provider on the GetUser implementation, so you can consolidate your extra properties you need into that database read.

我们过去做了很多次。与Thomas提到的类似,我们通常所做的是实现基于Microsoft SQL Memberhsip提供程序的新成员资格提供程序来执行此操作。我们从基础MembershipUser类继承,并添加我们希望在用户对象上拥有的任何自定义属性。您必须在GetUser实现上为Membership提供程序实现数据库读取,因此您可以将所需的额外属性合并到该数据库读取中。

If you are using SQL server, Microsoft has release the 2.0 code for it. You can get more information at Scott Gu's blog.

如果您使用的是SQL Server,Microsoft已为其发布了2.0代码。您可以在Scott Gu的博客上获得更多信息。

http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx

If you want to start from scratch, they also have good resources at MSDN.

如果你想从头开始,他们在MSDN上也有很好的资源。

http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx

and

http://msdn.microsoft.com/en-us/library/6tc47t75.aspx

Once you have implemented your provider, you can then add the Membership user to the Items collection of the current web context to get access to it from your code. The non extended properties from the base base user class are also available on the Request thread like normal.

实现提供程序后,可以将Membership用户添加到当前Web上下文的Items集合中,以便从代码中访问它。基本用户类的非扩展属性也可以像Request一样在Request线程上使用。

With the Microsoft release of the 2.0 version of the source code , we found it helped us alleviate some concerns that exist about reinventing. Another thing to consider for your implementations is based on your scenario, you can bypass implementing some of the code. An example of this would be the CreateUser code if you are hitting a back end system that already has the credential information.

随着微软发布的2.0版源代码,我们发现它帮助我们减轻了一些关于重新发明的担忧。您的实现需要考虑的另一件事是基于您的场景,您可以绕过实现某些代码。如果您正在使用已具有凭据信息的后端系统,则可以使用CreateUser代码。

#6


0  

It seems like you're relatively happy with your authentication process but you want to explore other options for session/settings.

您似乎对身份验证过程相对满意,但您想要探索会话/设置的其他选项。

My suggestion has to do with settings only (roles, preferences, etc.)

我的建议只与设置(角色,偏好等)有关。

In my opinion, having to traverse the whole technology stack from UI to Business Tier to DB tier to DB is sometimes a bit overkill. For data that isn't likely to change during a session, this adds a lot of overhead... There are potentially several data transformations happening (DB (Relational Format) -> ORM -> Web Service XML Serialization -> Web Tier deserialization).

在我看来,不得不遍历从UI到Business Tier到DB层到DB的整个技术堆栈有时候有点矫枉过正。对于在会话期间不太可能发生变化的数据,这会增加很多开销......可能会发生多次数据转换(DB(关系格式) - > ORM - > Web服务XML序列化 - > Web层序列化反序列化) 。

You might consider a session system that doesn't rely on a heavy RDBMS system or on the ASP.NET Caching / Session model. There are options that are very performant and that scale well.

您可能会考虑不依赖于繁重的RDBMS系统或ASP.NET缓存/会话模型的会话系统。有些选项非常高效且可以很好地扩展。

You could use RavenDB by Ayende Rahien (Built for .NET). Its main goal is to provide low latency, high performance access to schema-less JSON documents.

你可以使用Ayende Rahien的RavenDB(Built for .NET)。其主要目标是为无架构的JSON文档提供低延迟,高性能的访问。

Using this solution, you would set up ravenDB in the web tier so that access to data is very quick. The first time you authenticate and retrieve settings, you would store the userID and settings information in this session DB. Every time you load your controller after that, the settings data is accessible without having to go back to the RDBMS. This DB could also be used to cache other web related data.

使用此解决方案,您可以在Web层中设置ravenDB,以便快速访问数据。第一次验证和检索设置时,您会将userID和设置信息存储在此会话数据库中。每次在此之后加载控制器时,都可以访问设置数据,而无需返回到RDBMS。此DB还可用于缓存其他Web相关数据。

As for security, the settings data makes it to the web tier regardless of the method you use. This solution would be no more or less secure than the other options (more secure than an unencrypted cookie). If you needed to, you could encrypt the session data - but that will increase your overhead again.

至于安全性,无论您使用何种方法,设置数据都会使其成为Web层。此解决方案不会比其他选项更安全或更安全(比未加密的cookie更安全)。如果需要,您可以加密会话数据 - 但这会再次增加您的开销。

Just another one of the million options to consider.

只是需要考虑的百万选项中的另一个。

Good Luck,

Let us know what you decide!

让我们知道你的决定!

Patrick.

#1


11  

One of the rules about security is that you shouldn't try to do it yourself. There are many pitfalls in doing an authentication system correctly without leaving loopholes or backdoors. Thus, in that regard, you might consider the SqlMembershipProvider that comes with .NET. It can be used with MVC and provides the means to get roles and the current security context, is easy to setup and configure and will be more secure than rolling your own.

关于安全性的规则之一是你不应该自己尝试。在不留下漏洞或后门的情况下正确地进行身份验证系统存在许多缺陷。因此,在这方面,您可能会考虑.NET附带的SqlMembershipProvider。它可以与MVC一起使用,并提供获取角色和当前安全上下文的方法,易于设置和配置,并且比滚动自己更安全。

If you are not using SQL Server, you have a couple of choices. One solution would be to use something like SQL Server Express or SQL Server Compact Edition to maintain the credentials. Another solution would be to mimic the SqlMembrershipProvider database schema and then write a custom provider that communicates with that schema.

如果您不使用SQL Server,则有几个选择。一种解决方案是使用SQL Server Express或SQL Server Compact Edition之类的东西来维护凭据。另一种解决方案是模仿SqlMembrershipProvider数据库模式,然后编写与该模式通信的自定义提供程序。

The last choice would be to write a custom MembershipProvider class. While this is still rolling your own, it forces you into the structure of the MembershipProvider so that you can swap it out at a later date for a different one (e.g. ActiveDirectoryMembershipProvider) and provides a common interface for interacting with credentials and logins which for example enables easy use of the built-in Login control.

最后一个选择是编写自定义MembershipProvider类。虽然这仍然是您自己的,但它会强制您进入MembershipProvider的结构,以便您可以在以后将其交换为另一个(例如ActiveDirectoryMembershipProvider),并提供用于与凭证和登录进行交互的通用接口,例如可以轻松使用内置的Login控件。

If you are already using a MembershipProvider and are asking about storing additional user-specific data, then I would suggest the SqlProfileProvider with all the caveats I mentioned above about the SqlMembershipProvider. the ProfileProvider provides a structure for maintain user-specific data with the currently logged on user.

如果您已经在使用MembershipProvider并且询问存储其他特定于用户的数据,那么我建议SqlProfileProvider包含我上面提到的关于SqlMembershipProvider的所有警告。 ProfileProvider提供了一个结构,用于维护当前登录用户的用户特定数据。

For more information:

了解更多信息:

#2


1  

You could also implement a custom identity. They are very easy to implement, and they let you store whatever user information you want in Identity, which is then stored in the cookies that Identity puts down, so you're not hitting the DB every time to get that info.

您还可以实现自定义标识。它们非常容易实现,它们允许您在Identity中存储您想要的任何用户信息,然后将其存储在Identity放下的cookie中,这样您每次都不会访问数据库以获取该信息。

Just create a new class that inherits from GenericIdentity, and you'll be on your way.

只需创建一个继承自GenericIdentity的新类,您就可以了。

You of course have to be careful how much info you put there since it's in a cookie, but usually user related information in the case you're talking about here isn't so big.

你当然要小心你放在那里有多少信息,因为它在一个cookie中,但是你在这里讨论的情况下通常与用户相关的信息并不是那么大。

We use a custom identity to store a few bits of info about the user, and it works out pretty well.

我们使用自定义标识来存储有关用户的一些信息,并且效果非常好。

#3


0  

You could store an object in session that holds all the required user information. You will just need to add a property in the Controllers, Views or other base classes where you want to retrieve the user information/profile. This would be the authorisation info as opposed to any authentication info (eg Forms authentication)

您可以在会话中存储包含所有必需用户信息的对象。您只需要在控制器,视图或其他要检索用户信息/配置文件的基类中添加属性。这将是授权信息,而不是任何身份验证信息(例如,表单身份验证)

#4


0  

You might try "Windows Identity Foundation". I've been using it on one of my projects for a while. It allows for "claims-based authentication", which basically means that you get to designate "claims", strings of information that describe the user when she logs on.

您可以尝试“Windows Identity Foundation”。我已经在我的一个项目上使用它了一段时间。它允许“基于声明的身份验证”,这基本上意味着您可以指定“声明”,即在用户登录时描述用户的信息串。

Once logged on, the user's claims can be read from the HttpContext.Current.User field. You can also use "Role" claims that seamlessly integrate with a role-based authentication schema; meaning that you can give the user a "manager" role claim and then use `if (User.IsInRole("manager")).

登录后,可以从HttpContext.Current.User字段中读取用户的声明。您还可以使用与基于角色的身份验证架构无缝集成的“角色”声明;意思是你可以给用户一个“经理”角色声明,然后使用`if(User.IsInRole(“manager”))。

As an added bonus, WIF makes it very easy to re-use your login screen in other applications.

作为一个额外的好处,WIF可以很容易地在其他应用程序中重用您的登录屏幕。

All in all, it's very flexible, but the documentation is very poor. I've asked and answered a number of questions about "Windows Identity Foundation" on *.

总而言之,它非常灵活,但文档非常差。我已经在*上询问并回答了一些关于“Windows Identity Foundation”的问题。

#5


0  

We have done this quite a few times in the past. Similar to what Thomas mentions, what we have generally done is implemented a new Membership provider based on the Microsoft SQL Memberhsip provider to do this. We inherit from the base MembershipUser class and add any custom properties we would want to have on the user object. You have to implement a database read for the Membership provider on the GetUser implementation, so you can consolidate your extra properties you need into that database read.

我们过去做了很多次。与Thomas提到的类似,我们通常所做的是实现基于Microsoft SQL Memberhsip提供程序的新成员资格提供程序来执行此操作。我们从基础MembershipUser类继承,并添加我们希望在用户对象上拥有的任何自定义属性。您必须在GetUser实现上为Membership提供程序实现数据库读取,因此您可以将所需的额外属性合并到该数据库读取中。

If you are using SQL server, Microsoft has release the 2.0 code for it. You can get more information at Scott Gu's blog.

如果您使用的是SQL Server,Microsoft已为其发布了2.0代码。您可以在Scott Gu的博客上获得更多信息。

http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx

If you want to start from scratch, they also have good resources at MSDN.

如果你想从头开始,他们在MSDN上也有很好的资源。

http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx

and

http://msdn.microsoft.com/en-us/library/6tc47t75.aspx

Once you have implemented your provider, you can then add the Membership user to the Items collection of the current web context to get access to it from your code. The non extended properties from the base base user class are also available on the Request thread like normal.

实现提供程序后,可以将Membership用户添加到当前Web上下文的Items集合中,以便从代码中访问它。基本用户类的非扩展属性也可以像Request一样在Request线程上使用。

With the Microsoft release of the 2.0 version of the source code , we found it helped us alleviate some concerns that exist about reinventing. Another thing to consider for your implementations is based on your scenario, you can bypass implementing some of the code. An example of this would be the CreateUser code if you are hitting a back end system that already has the credential information.

随着微软发布的2.0版源代码,我们发现它帮助我们减轻了一些关于重新发明的担忧。您的实现需要考虑的另一件事是基于您的场景,您可以绕过实现某些代码。如果您正在使用已具有凭据信息的后端系统,则可以使用CreateUser代码。

#6


0  

It seems like you're relatively happy with your authentication process but you want to explore other options for session/settings.

您似乎对身份验证过程相对满意,但您想要探索会话/设置的其他选项。

My suggestion has to do with settings only (roles, preferences, etc.)

我的建议只与设置(角色,偏好等)有关。

In my opinion, having to traverse the whole technology stack from UI to Business Tier to DB tier to DB is sometimes a bit overkill. For data that isn't likely to change during a session, this adds a lot of overhead... There are potentially several data transformations happening (DB (Relational Format) -> ORM -> Web Service XML Serialization -> Web Tier deserialization).

在我看来,不得不遍历从UI到Business Tier到DB层到DB的整个技术堆栈有时候有点矫枉过正。对于在会话期间不太可能发生变化的数据,这会增加很多开销......可能会发生多次数据转换(DB(关系格式) - > ORM - > Web服务XML序列化 - > Web层序列化反序列化) 。

You might consider a session system that doesn't rely on a heavy RDBMS system or on the ASP.NET Caching / Session model. There are options that are very performant and that scale well.

您可能会考虑不依赖于繁重的RDBMS系统或ASP.NET缓存/会话模型的会话系统。有些选项非常高效且可以很好地扩展。

You could use RavenDB by Ayende Rahien (Built for .NET). Its main goal is to provide low latency, high performance access to schema-less JSON documents.

你可以使用Ayende Rahien的RavenDB(Built for .NET)。其主要目标是为无架构的JSON文档提供低延迟,高性能的访问。

Using this solution, you would set up ravenDB in the web tier so that access to data is very quick. The first time you authenticate and retrieve settings, you would store the userID and settings information in this session DB. Every time you load your controller after that, the settings data is accessible without having to go back to the RDBMS. This DB could also be used to cache other web related data.

使用此解决方案,您可以在Web层中设置ravenDB,以便快速访问数据。第一次验证和检索设置时,您会将userID和设置信息存储在此会话数据库中。每次在此之后加载控制器时,都可以访问设置数据,而无需返回到RDBMS。此DB还可用于缓存其他Web相关数据。

As for security, the settings data makes it to the web tier regardless of the method you use. This solution would be no more or less secure than the other options (more secure than an unencrypted cookie). If you needed to, you could encrypt the session data - but that will increase your overhead again.

至于安全性,无论您使用何种方法,设置数据都会使其成为Web层。此解决方案不会比其他选项更安全或更安全(比未加密的cookie更安全)。如果需要,您可以加密会话数据 - 但这会再次增加您的开销。

Just another one of the million options to consider.

只是需要考虑的百万选项中的另一个。

Good Luck,

Let us know what you decide!

让我们知道你的决定!

Patrick.