我正在研究在我的MVC3应用程序中实现身份验证的各种方法。我想使用自己的代码进行身份验证 - 类似于Is it possible to create a Logon System with ASP.NET MVC but not use the MembershipProvider? (我知道还有其他方法。)我想知道一旦我使用一个用户进行身份验证在这些方法中,如何将用户信息提供给Controller构造函数。 (根据用户信息,我的意思是用户名或用户ID)。
我考虑的其中一个选项是将这些信息放入Session
。这是有效的,但是很难测试,因为我从Session
中得到Context
,这在测试期间不存在。
我很感激有关如何将用户信息传递给控制器构造函数的任何想法。
答案 0 :(得分:0)
没有。不要使用Session进行身份验证。它不太安全,而且不稳定(会话可以被服务器随意销毁)。
在MVC中,你根本不需要使用成员资格,但是......我会强调一点但是......正确地进行身份验证并不是一项简单的任务。它很容易弄错,甚至没有意识到它。即使你知道你在做什么。应该对其进行大量分析,测试,验证和重新分析。
我建议,如果你不想扩展这项工作,你应该只使用默认的提供者(你可以选择几种)。
但无论如何,如果你决心自己动手,你只需要一些方法来验证用户。 MVC没有像WebForms那样与成员资格提供程序集成。它使用它是为了方便。如果您查看在创建Internet项目时为您生成的默认AccountController
,则只需调用Membership.VerifyUser()
。
真正重要的是身份验证cookie系统,MS以FormsAuthentication
类的形式提供。我非常强烈建议将其用于cookie管理,除非你真的真的知道你在做什么。
只需查看AccountController
,这应该是非常明显的。 FormsAuthentication
是集成到应用程序中的部分,并告诉asp.net用户已经过身份验证。它使用安全的加密cookie,设计精良(甚至允许您以加密格式存储自己的附加数据)。
Forms Authentication是一组一起工作以提供透明身份验证机制的类,并集成到MVC和Asp.net WebForms中。它们基本上是IPrincipal和IIdentity系统的一个实现,它是asp.net的组成部分(如果你键入User.IsAuthenticated
,它使用IPrincipal接口)。
答案 1 :(得分:0)
在我的原始帖子中,我正在考虑将用户信息传递给Controller
构造函数。我不希望Controller
依赖HttpContext
,因为这会使测试变得困难。
虽然我感谢 Mystere Man 的解决方案,但我希望以下备用解决方案可以帮助某些人。我有一个小项目(大约十几个控制器)所以它不是太糟糕。
我基本上创建了继承自ControllerFactory
的自定义DefaultControllerFactory
:
public class MyCustomControllerFactory : DefaultControllerFactory
{
public MyCustomControllerFactory ()
{
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
return null;
}
else
{
//Example of User Info - Customer ID
string customerIDStr = requestContext.HttpContext.Session["CustomerID"].ToString();
int customerID = Int32.Parse(customerIDStr);
//Now we create each of the Controllers manually
if (controllerType == typeof(MyFirstController))
{
return new MyFirstController(customerID);
}
else if (controllerType == typeof(MySecondController))
{
return new MySecondController(customerID);
}
//Add/Create Controllers similarly
else //For all normal Controllers i.e. with no Arguments
{
return base.GetControllerInstance(requestContext, controllerType);
}
}
}
}
然后我在ControllerFactory
Global.asax.cs
方法中设置了Application_Start()
。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactory ());
}
P.S。我研究过使用像Ninject这样的DI容器,但我认为它们对于我目前的项目来说太复杂了。我会在几个月内看到它们,使用它们真的很有意义。