【问题标题】:Defining a User with User.Identity.Name in controller constructor在控制器构造函数中使用 User.Identity.Name 定义用户
【发布时间】:2009-08-21 17:17:26
【问题描述】:

对于要与用户帐户交互的操作,我想创建一个“TheUser”对象,并在我的控制器上的任何操作完成后立即将该对象添加到“ViewData[“TheUser”]”调用。

如果用户已登录,它将从数据库中获取用户的信息,如果没有,“TheUser”对象将为空。

我尝试在控制器构造函数中访问“User.Identity.Name”,但它不是在调用任何操作之前创建的。

我正在查看自定义授权过滤器,但这些过滤器不允许我创建“TheUser”对象并将其存储在 ViewData 中。

这是我想要完成的一个简短的 sn-p:

[Authorize]
public class HomeController : Controller
{
    User TheUser;

    public HomeController()
    {
        TheUser = User.Identity.IsAuthenticated ? UserRepository.GetUser(User.Identity.Name) : null;

        ViewData["TheUser"] = TheUser;  
    }
}

【问题讨论】:

标签: c# asp.net-mvc authorization


【解决方案1】:

我创建了一个自定义的 Controller 基类并向其添加了“CurrentUser”属性。

在 Initialize 方法中,我放置了获取用户的逻辑,然后将其添加到 ViewData 和控制器的“CurrentUser”属性中。

我让我的控制器继承了自定义的基本 Controller 类,并且我能够在控制器中的任何位置引用“CurrentUser”变量:

public class CustomControllerClass : Controller
{
    public User CurrentUser { get; set; }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        if (requestContext.HttpContext.User.Identity.IsAuthenticated)
        {
            string userName = requestContext.HttpContext.User.Identity.Name;
            CurrentUser = UserRepository.GetUser(userName);
        }

        ViewData["CurrentUser"] = CurrentUser;                
    }
}

【讨论】:

  • 当我从 BaseController 继承我的 Controller 时,我的所有 Web 请求在执行 BaseController 的 Execute 方法后停止,并且不转到 Action 方法。我在浏览器中得到一个空白页面。我们还需要做些什么来运行它吗?
  • Puneet,请看看我的编辑。我最初的答案是针对 ASP.NET MVC 1。我对其进行了更新以覆盖 Initialize 方法,因为这是在 MVC 2 和 3 中执行此类操作的地方
  • 非常感谢,我真的很感激。找了半天,你的回答很好,简洁。
【解决方案2】:

我使用构造函数方法以类似的方式设置我的基本控制器,并且我能够通过以下方式读取此用户信息。注意:我只存储 UserId,而不是 User 对象,但我的代码的重点是展示如何在 contriuctor 方法中获取所需的信息。

public abstract class BaseController : Controller
{
    int _UserId = 0;

    public int UserId
    {
        get { return _UserId; }
        set { _UserId = value; }
    }

    public BaseController()
    {
        var userFromAuthCookie = System.Threading.Thread.CurrentPrincipal;

        if (userFromAuthCookie != null  && userFromAuthCookie.Identity.IsAuthenticated) // && !String.IsNullOrEmpty(userFromAuthCookie.Identity.Name))
        {
            busUser userBO = AceFactory.GetUser();
            string userNameFromAuthCookie = userFromAuthCookie.Identity.Name;
            _UserId = userBO.GetUserIdByUsername(userNameFromAuthCookie);
        }
    }

【讨论】:

  • 我还尝试使用 User.Identity 返回用户 - System.Threading.Thread.CurrentPrincipal 已为我修复 - 非常感谢
  • System.Threading.Thread.CurrentPrincipal 帮助我在实际构造函数中访问我的用户 ID。谢谢。
【解决方案3】:
public abstract class YourController : Controller
{
    public YourController()
    {
        var user = System.Threading.Thread.CurrentPrincipal;

        TheUser = User.Identity.IsAuthenticated ? UserRepository.GetUser(user.Identity.Name) : null;

        ViewData["TheUser"] = TheUser;  
    }
}

【讨论】:

    【解决方案4】:

    是否必须为每个控制器操作或仅针对特定操作实例化用户?

    如果您创建一个 ActionFilterAttribute,您确实可以访问控制器上下文。不确定 AuthorizationFilters 是否如此,但您可以尝试以下方法:

    public class MyCustomFilter: ActionFilterAttribute
    {
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.Controller.ViewData["TheUser"] = User.Identity.IsAuthenticated ? UserRepository.GetUser(User.Identity.Name) : null;
            base.OnActionExecuting(filterContext);
        }
    }
    

    然后,将此附加到必要的控制器操作。

    【讨论】:

    • TheUser 它用于每个操作。令我困惑的是,虽然 [Authorize] 确保用户经过身份验证,但我无权访问 User.Identity,但我可以访问 ViewData。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 2018-10-27
    • 2014-09-29
    • 2019-05-22
    • 1970-01-01
    相关资源
    最近更新 更多