2010-03-30 126 views
4

我有一个MVC应用程序,我有一个用户类,用户也可以模拟另一个用户(仅限管理员用户)。ASP.NET MVC创建一个模拟用户

所以我有下面的代码验证请求并实例化我的User类的版本。

然后它会尝试从Session对象中获取模拟用户,但Session不能在global.asax中的此方法中使用。

希望这是有道理的。

我该怎么办?

我的问题我猜是在global.asax方法的哪一点你可以访问每个请求的Session对象?

protected void Application_OnAuthenticateRequest(object sender, EventArgs e) 
{ 
    IMylesterService service = ObjectFactory.GetInstance<IMylesterService>(); 

    if (Context.User != null) 
    { 
     if (Context.User.Identity.IsAuthenticated) 
     { 
      User user = service.GetUser(Context.User.Identity.Name); 
      if (user == null) 
       throw new ApplicationException("Context.user.Identity.name is not a recognized user"); 

      User impersonatedUser = (User)this.Session["ImpersonatedUser"]; 
      if (impersonatedUser == null) 
       user.ImpersonatedUser = user; 
      else 
       user.ImpersonatedUser = impersonatedUser; 

      System.Threading.Thread.CurrentPrincipal = Context.User = user; 
      return; 
     } 
    } 
    User guest = service.GetGuestUser(); 
    guest.ImpersonatedUser = guest; 

    System.Threading.Thread.CurrentPrincipal = Context.User = guest; 
} 
+0

最近我一直有这个确切的问题,并希望有人会参加。我能够开始工作的唯一的事情就是使用OnSessionStart,但是如果你没有通过身份验证时,你想念你机会。我正在移植一个ASP.NET应用程序,其中在共享基本ASPX中运行的某些会话代码现在需要去其他地方... – 2010-03-30 04:07:36

回答

0

在AuthenticateRequest期间会话将不可用:您需要做的是将所需信息标记到Identity.userData;因此,例如,如果你在哪里使用窗体身份验证请执行以下操作:

void Application_AuthenticateRequest(object sender, EventArgs e) 
{ 
    if (Context.User != null) 
    { 
    if (Context.User.Identity.IsAuthenticated) 
    { 
     // retrieve the value 
     var id = (FormsIdentity)Context.User.Identity; 
     var myvalue = id.Ticket.UserData; // "Here you are" 
    } 
    } 
} 

对于使用形式符号,你需要编写自定义的cookie: MVC - >类FormsAuthenticationService:IFormsAuthenticationService

public static void SetAuthenticationCookie(HttpContextBase context, FormsAuthenticationTicket ticket) 
{ 
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName) 
     { 
      Value = FormsAuthentication.Encrypt(ticket), 
      Secure = FormsAuthentication.RequireSSL, 
      Domain = FormsAuthentication.CookieDomain, 
      HttpOnly = true, 
      Expires = DateTime.Now.AddMinutes(15) 
     }; 

    if (!context.Request.IsSecureConnection && FormsAuthentication.RequireSSL) 
    { 
     throw new HttpException("Ticket requires SSL."); 
    } 
    context.Response.Cookies.Add(cookie); 
} 
public static FormsAuthenticationTicket CreateTicket(HttpContextBase context, string emailAddress, string userData, bool persist) 
{ 
    return new FormsAuthenticationTicket(1, emailAddress, DateTime.Now, DateTime.Now.AddMinutes(15), persist, userData, FormsAuthentication.FormsCookiePath); 
} 

最后在SignIn中,您现在可以通过调用CreateTicket(...)创建所需的票据,然后通过SetAuthenticationCookie(...)将其写出。

public void SignIn(string userName, string password) 
{ 
    if(CheckUserValid(userName,password, out string email)) 
    { 
     var ticket = CreateTicket(email, "Here you are", true); 
     SetAuthenticationCookie(HttpContext.Current.Base(), ticket); 
    } 
} 

我从来没有使用过它,但承担的AcquireRequestState期间会话状态分配:

public void Init(HttpApplication context) 
{ 
    context.AcquireRequestState += new EventHandler(context_AcquireRequestState); 
} 
0

我需要在Global.asax中访问会话的这个相同的问题,最后通过将我的代码移动到AcquireRequestState处理程序来解决此问题,该处理程序在身份验证通过后发生。

protected void Application_AcquireRequestState(Object sender, EventArgs e) 
    { 
     if (Request.IsAuthenticated && Context.Session != null) 
     { 
      // access Context.Session 
     } 
    } 

这会激发很多并且当前上下文并不总是有一个有效的会话对象,因此检查。

编辑:必须添加IsAuthenticated检查 - 注销时出现空错误。现在效果很好。

1

尝试创建一个授权过滤器:

public class CustomAuthorizationFilter : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) 
    { 
     // perform your authorization here 
     // full access to HttpContext and session 
    } 
} 

然后,您可以将此属性应用到您的控制器。理想情况下,您将拥有一个其他所有控制器都从其继承的基本控制器,并且您可以在该控制器上的类级别应用该属性。然后,您的所有请求都将被授权并应用您上面编码的模拟。