c# - MVC4 自定义表单例份验证 - 无法将 System.Web.HttpContext.Current.User 转换为 CustomPrincipal

标签 c# asp.net asp.net-mvc asp.net-mvc-4 forms-authentication

我正在 .Net MVC4 中构建网站,并尝试使用 CustomPrincipal 对象实现我自己的表单例份验证。

这是我的登录方法...

public void Login(string email)
{
    var user = _userManager.GetUserByEmail(email);

    var encryptedCookieContent = FormsAuthentication.Encrypt(new FormsAuthenticationTicket(1, user.Email, DateTime.Now, DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
        false, user.Id + "|" + user.AccountId + "|" + user.RoleId + "|" + user.Role.Name, FormsAuthentication.FormsCookiePath));

    var formsAuthenticationTicketCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookieContent)
    {
        Domain = FormsAuthentication.CookieDomain,
        Path = FormsAuthentication.FormsCookiePath,
        HttpOnly = true,
        Secure = FormsAuthentication.RequireSSL
    };

    HttpContext.Current.Response.Cookies.Add(formsAuthenticationTicketCookie);
}

这是我的自定义委托(delegate)人

public class CustomPrincipal : IPrincipal
{
    public CustomPrincipal(IIdentity identity, int userId, int accountId, string role, int roleId)
    {
        Identity = identity;
        Role = role;
        RoleId = roleId;
        UserId = userId;
        AccountId = accountId;
    }

    public bool IsInRole(string role)
    {
        return Role == role;
    }

    public bool IsInRole(int roleId)
    {
        return RoleId == roleId;
    }

    public IIdentity Identity { get; private set; }

    public string Role { get; private set; }
    public int RoleId { get; private set; }

    public int UserId { get; private set; }
    public int AccountId { get; private set; }
}

我没有实现自定义身份实例,我只是重复使用 GenericIdentity。 在我的 Global.asax 文件中,我的 Application_AuthenticateRequest 方法是这样装配的...

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    if (Request.IsAuthenticated)
    {
        var formsCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        if (formsCookie != null)
        {
            var ticket = FormsAuthentication.Decrypt(formsCookie.Value);
            var principal = PrincipalConfig.CreatePrincipal(ticket);
            System.Web.HttpContext.Current.User = Thread.CurrentPrincipal = principal;
        }
    }
}

PrincipalConfig.CreatePrincipal 是将我的自定义委托(delegate)人对象放在一起的方法。这基本上只是填写用户数据...像这样...

public static CustomPrincipal CreatePrincipal(FormsAuthenticationTicket ticket)
        {
            var userData =  ticket.UserData.Split('|');
            var principal = new CustomPrincipal(new GenericIdentity(ticket.Name), Convert.ToInt32(userData[0]), Convert.ToInt32(userData[1]), userData[3], Convert.ToInt32(userData[2]));
            return principal;
        }

现在,回到 global.asax 文件中的 Application_AuthenticateRequest,您可以看到我正在使用新创建的 CustomPrincipal 对象并将其分配给 System.Web.HttpContext.Current.User。

这样做之后,如果我将以下内容放在即时窗口中,同时仍在 Application_AuthenticateRequest 方法中...

System.Web.HttpContext.Current.User as CustomPrincipal

正如我所期望的那样,我在 CustomPrincipal 对象中显示了所有数据。

但是,如果我稍后(在其他一些 Controller 操作中)尝试访问 System.Web.HttpContext.Current.User 并将其转换为 CustomPrincipal,它将返回 null。

同样,对于在应用程序中发出的每个请求,我都能够从 Application_AuthenticateRequest 方法内的 FormsAuthentication cookie 中解密 FormsAuthenticationTicket,并且我找到了我的所有 UserData。因此,似乎正在正确创建和读取 cookie。但是,当新的 CustomPrincipal 分配给 System.Web.HttpContext.Current.User 时,从那时到我尝试在另一个 Controller 内再次访问它的时间似乎存在某种断开连接。

谁能看出我这里可能做错了什么?

如果我需要澄清任何事情,请告诉我。

谢谢

最佳答案

我不确定你在用

Request.IsAuthenticated

正确。

Request.IsAuthenticated 属性基本上返回与 Context.User.Identity.IsAuthenticated 属性相同的值。在您的代码中,它应该始终返回 false,因此分配自定义主体的代码永远不会触发。

您可以通过在 Controller 方法中设置断点并检查代码中 Context.Current.User 的类型来稍微调试一下。是通用身份吗?如果是这样,则您的委托(delegate)人从未被分配。

关于c# - MVC4 自定义表单例份验证 - 无法将 System.Web.HttpContext.Current.User 转换为 CustomPrincipal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18863867/

相关文章:

c# - 从 DateTime(出生日期)算起的年龄

c# - 使用事件和 BackgroundWorker 更新导致竞争条件的 UI

c# - 当在 Controller 构造时不知道存储库时,如何在 Controller 中注入(inject)存储库?

c# - 如何在 asp.net 下载文件之前调用 javascript 函数?

javascript - 在 jquery post ASP.NET MVC 之前转义字符的最佳方法

c# - 在 Entity Framework 中使用存储过程的乐观并发

c# - 是否可以使用 .NET 异步方法获得良好的堆栈跟踪?

c# - Gridview 中的多列排序?

asp.net-mvc - 如何在 Visual Studio 2012 或 Visual Studio 2013 中打开旧的 MVC 项目?

asp.net-mvc - 任何支持具有不同切片半径的饼图的 ASP.NET MVC 友好图表控件?