在 HttpContext 中保留 CustomPrincipal 类型时遇到问题

Trouble retaining CustomPrincipal type in HttpContext

我有一个 MVC 应用程序,但在向我的视图展示自定义主体时遇到了问题。它具有以下 类 可帮助我管理身份验证 cookie。

public class AuthenticationManager
{
    public void SetAuthCookie(UserViewModel user)
    {
        var serializeModel = new CustomPrincipalSerializeModel
        {
            Id = user.UserId,
            Email = user.Email,
            Name = user.Name
        };
        var serializer = new JavaScriptSerializer();
        var customPrincipal = customPrincipalMapper.Convert(serializeModel);
        var httpContext = ContextHelper.GetHttpContextBase();
        httpContext.User = customPrincipal;
        var userData = serializer.Serialize(serializeModel);
        var authTicket = new FormsAuthenticationTicket(1, serializeModel.Email, DateTime.Now, DateTime.Now.AddYears(5), false, userData);
        var encTicket = FormsAuthentication.Encrypt(authTicket);
        var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
        httpContext.Response.Cookies.Add(authCookie);
    }
}

public static class ContextHelper
{
    public static HttpContextBase GetHttpContextBase()
    {
        return new HttpContextWrapper(HttpContext.Current);
    }
}

我还有以下 BaseViewPage 类 允许我向当前用户展示我的观点:

public abstract class BaseViewPage : WebViewPage
{
    public virtual new CustomPrincipal User
    {
        get { return base.User as CustomPrincipal; }
    }
}

public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
    public virtual new CustomPrincipal User
    {
        get { return base.User as CustomPrincipal; }
    }
}

FWIW,这需要 <pages pageBaseType="Giftster.Web.Views.BaseViewPage"> 在我的视图的 Web.config 文件中。

立即,httpContext.User = customPrincipal; 行在 AuthenticationManager.SetAuthCookie() 中运行后,ContextHelper.GetHttpContextBase().User returns 的对象类型是 CustomPrincipal。但是,如果我刷新页面,并在 BaseViewPage 中放置一个断点,base.User as CustomPrincipal(和 ContextHelper.GetHttpContextBase().User as CustomPrincipal 就此而言)等于 null。但是,base.User 不为空:它属于 GenericPrincipal 类型,因此存在转换问题或 storing/retrieving 正确类型的问题。

为什么我的 BaseViewPage 中的 base.User 不是 CustomPrincipal 类型?

提前致谢。

您需要从每个请求中的 cookie 创建您的 CustomPrincipal 并将其添加到当前上下文中。将以下内容添加到 Global.asax.cs 文件

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
  // Get the authentication cookie
  HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
  // If the cookie can't be found, don't issue the ticket
  if (authCookie == null)
  {
    return;
  }
  // Extract the forms authentication cookie
  FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
  // Deserialise user data
  JavaScriptSerializer serializer = new JavaScriptSerializer();
  CustomPrincipalSerializeModel data = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);
  // Create principal
  CustomPrincipal principal = new CustomPrincipal(authTicket.Name);
  // Set the properties of CustomPrincipal
  principal.Email = data.Email;
  .... // etc
  // Assign to current context
  HttpContext.Current.User = principal;
}

另请注意,您的 SetAuthCookie() 方法中不需要以下行

httpContext.User = customPrincipal;

您还可以考虑将以下内容添加到 BaseController(所有其他控制器都从中派生),以便可以在每个控制器方法中轻松访问 CustomPrincipal 属性

public new CustomPrincipalSerializeModel User
{
  get { return (CustomPrincipal)HttpContext.User; }
}