2015-04-23 1 views
1

Я знаю, что REST является апатридом, но это требование по дизайну. Нам нужно аутентифицировать запросы API из его родительского приложения, которое является традиционным приложением ASp.net Web Form.Обмен сеансом между веб-приложением Asp.net и веб-интерфейсом Asp.net Web2 (Asp.net Web API2 размещен под веб-приложением Asp.net, доступным для одной конфигурации)

У меня есть совместная сессия в соответствии с этими URL-адресами. http://weblogs.asp.net/lichen/sharing-session-state-over-multiple-asp-net-applications-with-asp-net-state-server

How to maintain the same session id across multiple web applications in ASP.NET

http://www.codeproject.com/Articles/27090/Sharing-Session-Across-Applications

Global.asax код из обоих приложения для обмена сессии

public override void Init() 
    { 
     base.Init(); 
     try 
     { 
      // Get the app name from config file... 
      string appName = ConfigurationManager.AppSettings["ApplicationName"]; 

      Logger.LogEx(string.Format("{0} - {1}", appName, appName)); 
      // regenerateId(); 
      if (!string.IsNullOrEmpty(appName)) 
      { 
       foreach (string moduleName in this.Modules) 
       { 
        IHttpModule module = this.Modules[moduleName]; 
        SessionStateModule ssm = module as SessionStateModule; 
        Logger.LogEx(string.Format("module {0} - ssm {1}", module, ssm)); 
        if (ssm != null) 
        { 
         FieldInfo storeInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.Instance | BindingFlags.NonPublic); 
         SessionStateStoreProviderBase store = (SessionStateStoreProviderBase)storeInfo.GetValue(ssm); 
         if (store == null) //In IIS7 Integrated mode, module.Init() is called later 
         { 
          FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic); 
          HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null); 
          FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic); 
          Logger.LogEx(string.Format("theRuntime {0} - appName {1}", theRuntime, appName)); 
          appNameInfo.SetValue(theRuntime, appName); 
         } 
         else 
         { 
          Type storeType = store.GetType(); 
          if (storeType.Name.Equals("OutOfProcSessionStateStore")) 
          { 
           FieldInfo uribaseInfo = storeType.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic); 
           uribaseInfo.SetValue(storeType, appName); 
          } 
         } 
        } 
       } 
      } 
     } 


     catch (Exception ex) 
     { 

     } 
    } 

Я состояние сервера включен в web.cofing

sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:122233" cookieless="false" timeout="240" stateNetworkTimeout="3600" /> 

Код, который я пытаюсь выбрать для сеанса, сохраненного/разделяемого из родительского приложения в приложении child (Web Api2).

protected void Application_AcquireRequestState(object sender, EventArgs e) 
    { 
     try 
     { 
      string loginMethod = ""; 
      string sFileName = ""; 
      string userName = ""; 
      //string sFileExt = Strings.LCase("" + System.IO.Path.GetExtension(sender.request.filepath.ToString())); 
      //string serverName = HttpUtility.UrlEncode(Request.ServerVariables("SERVER_NAME")); 
      //ILog log1 = log4net.LogManager.GetLogger(HttpContext.Current.CurrentHandler.GetType()); 

      if ((HttpContext.Current.Session == null || HttpContext.Current.Session["UserID"] == null) && ConfigurationManager.AppSettings["SSOEnabled"] == "1") 
      { 
       Logger.LogEx("Session is null"); 
       userName = "" + GetDomainUserName(HttpContext.Current.User.Identity); 
       string domainName = "" + GetDomainName(HttpContext.Current.User.Identity); 
       loginMethod = "Windows Authentication"; 


       if (!string.IsNullOrEmpty(userName)) 
       { 
        Logger.LogEx("Windows userName extracted"); 
        Logger.LogEx(userName); 
        Logger.Log(String.Format("Connecting to API with windows username {0}", userName)); 

        } 
      else if ((HttpContext.Current.Session == null || HttpContext.Current.Session["UserID"] == null)) 
      { 
       Logger.LogEx("Session is null or UserId not found, exception is thrown"); 
       throw new HttpResponseException(System.Net.HttpStatusCode.Unauthorized); 
      } 
      else if ((HttpContext.Current.Session != null && HttpContext.Current.Session["UserID"] != null)) 
      { 
       loginMethod = "User is logged in via application Login interface"; 
       Logger.LogEx("userName is extracted from Shared Session"); 
       userName = HttpContext.Current.Session["UserName"].ToString(); 
      } 

      if (userName != null && userName != "") 
      { 
       Logger.LogEx(loginMethod); 

      } 
      else 
      { 
       Logger.LogEx("User Name is blank"); 
       Logger.Log("User should be logged in using Application Login Interface"); 
       throw new Exception("Unauthorized: User should be logged in using Application Login interface"); 
      } 
      Logger.Log(String.Format("Start request for {0}", HttpContext.Current.Request.Url.ToString())); 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(ex); 
      throw; 
     } 


    } 

При аутентификации устанавливается в Windows, а затем «HttpContext.Current.User» доступен, и мы позволяем API, чтобы получить доступ.

Такая же компоновка должна работать, когда установлена ​​анонимная проверка подлинности, этот случай «HttpContext.Current.Session» должен содержать значения сеанса, установленные родителем, но сам сеанс Null.

Когда мы включаем сеанс в API, сеанс не имеет значения null, но значения из родительского приложения недоступны.

protected void Application_PostAuthorizeRequest() 
{ 
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); 
} 

Моя цель для доступа к переменным сеанса, установленные «Родитель Веб-сайт», чтобы «ребенок Web Api 2 App», пожалуйста, помогите.

ответ

0

Я нашел решение моей проблемы!

Сеанс должен быть включен непосредственно перед AcquireRequestState события т.е.

protected void Application_PostMapRequestHandler(object sender, EventArgs e) 
    { 
     System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); 
    } 
Смежные вопросы