2010-03-30 88 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 
    } 
} 

然後,您可以將此屬性應用到您的控制器。理想情況下,您將擁有一個其他所有控制器都從其繼承的基本控制器,並且您可以在該控制器上的類級別應用該屬性。然後,您的所有請求都將被授權並應用您上面編碼的模擬。