2010-01-06 20 views
1

我知道之前已经提出过类似的问题,但我找不到能够专门处理ASP.NET MVC(以及控制器方面)的重复内容。设置/获取用户是否登录信息的最佳实践

我的问题如下:

在MVC模式,我的理解是,控制器应该处理使用的HttpContext,以确定谁登录,如果有的话。这是控制器可以将这些信息呈现给视图,以便视图本身不必执行这些查找。

有没有关于如何做的事实标准?

我目前的设置如下[简体]

我有一个BaseController,其中我的所有其他控制器继承。

BaseController,我执行以下重写:

protected override void Initialize(System.Web.Routing.RequestContext requestContext) 
{ 
    base.Initialize(requestContext); 
    ViewData["IsUserLoggedIn"] = IsUserLoggedIn; // bool property checking HttpContext.User.Identity.IsAuthenticated; 
    ViewData["CurrentUser"] = CurrentUser; // Property returning logged in user, or null. 

} 

然后,自然地,在我的意见,我可以检查ViewData的值。

怎么办?我想知道我的设置是否有问题,如果有,有什么问题?我对解决方案并不满意,主要是因为我对周期不太熟悉,而且我不确定自己的代码是否放在正确的位置。

我知道这里可能没有“一个答案绑定他们”,我接受的答案提供了最深入的见解。

回答

2

我通常将一个加密的元素放入cookie中。该元素可以是任何东西,但我通常把它作为用户名。

然后在Global.asax.cs中实现Application_AuthenticateRequest。每次加载页面时,系统都会调用此方法。在该方法中,我检查cookie,如果存在,我尝试加载用户。如果用户加载成功,那么我知道我有一个登录用户,并将当前线程当前Principal属性设置为该用户。

一旦在当前线程上设置了CurrentPrincipal,您就可以从Controller,View,Business Layer,以及您的执行路径中的任意位置访问该用户。

如果由于某些原因我不能使用cookie,那么我会在ViewData中传递它(再次加密以防万一),并将其存储在隐藏变量中。然后,当Controller :: OnActionExecuting运行时,我执行与AuthenticateRequest中通常所做的相同的工作(即加载用户并将其放到线程中)。

+0

有趣的方法。您的cookie方案如何与FormsAuthentication cookie相关联(当然,如果您使用表单身份验证)? – Terje 2010-01-09 19:28:09

+0

我没有使用FormsAuthentication,但我确实使用了常规的FormsAuthenticationTicket和HttpCookie。 当用户尝试登录时,我的控制器首先会调用我的域名层以尝试登录该用户。如果成功,那么我的控制器将创建一个包含我的加密用户名的FormsAuthenticationTicket对象,将它放入一个HttpCookie中,并将该Cookie放入Response.Cookies集合中。 在过去,我还必须添加一些东西到系统中以跟踪用户实际登录的情况(即,您从票据载入用户,然后检查他们是否也已登录)。 – 2010-01-12 15:23:47

+0

我一直在寻找见解,并且我得到了一些。谢谢。我会研究这种方法,并从我自己的经验中看到它与我目前使用的相比如何。跟踪用户是否登录;我用我的用户表中的最后一个活动标记来处理它,并在每次调用BaseController的Initialize时更新它。 – Terje 2010-01-15 12:42:27

0

我有一个BaseController类,所有我的控制器继承自。它有一个存储在会话中的“CurrentUser”属性。我的控制器的完整代码有更多的逻辑来检索用户,但这是基本的想法。

public class BaseController : Controller 
{ 

User _currentUser = null; 
public User CurrentUser 
{ 
    get 
    { 
     if (_currentUser == null) 
      _currentUser = (User)HttpContext.Session["CurrentUser"]; 

     return _currentUser; 

    } 
    set 
    { 
     _currentUser = value; 
     HttpContext.Session["CurrentUser"] = value; 
     } 
    } 
} 


} 

我的模型都从BaseModel类继承,它也具有CurrentUser属性。

public class BaseModel 
{ 
    public User CurrentUser { get; set; } 
} 

public class HomeIndexData : BaseModel 
{ 

} 

然后我的控制器将用户传递给允许我使用强类型视图的模型。

[HttpGet] 
public ActionResult Index() 
{ 
    HomeIndexData data = new HomeIndexData(); 
    data.CurrentUser = this.CurrentUser; 

    return View(data); 
} 

使用这种技术,我也可以使用BaseModel建立一个强类型的母版页。

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseModel>" %> 
+0

我在以前的项目中使用过类似的方法。大多数情况下,它运行良好,但在某些情况下,扩展BaseModel没有意义(或不可能)。 (想象直接映射到DataTable类,或使用来自外部项目.dll文件的模型对象)。所以我结束了与ViewData。 另外,您使用Session作为CurrentUser属性。这是否有一个好的理由?例如,为什么你不能使用Controller.HttpContext.User.Identity?或者更好的问题是,你为什么认为这是一个糟糕的主意? – Terje 2010-01-09 19:34:10

+0

拥有自定义用户对象而不是User.Identity使其在我们的情况下更具可扩展性。例如,我们的母版页有一个部分显示用户的名字和姓氏,这是我们无法用User.Identity.Name做的。 就个人而言,如果我在应用程序需要的DataTable中有项目,我宁愿制作POCO并使用DataTable填充它。 – 2010-01-11 15:00:51