Asp.net Web 应用程序和 Asp.net Web API2 之间的共享会话(Asp.net Web API2 托管在 Asp.net Web 应用程序访问一种配置下)

Sharing Session between Asp.net Web Application and Asp.net Web API2 (Asp.net Web API2 is hosted under Asp.net Web App accessing one configuration)

我知道 REST 是无状态的,但这是设计要求。 我们需要验证 API 来自其父应用程序的请求,这是一个传统的 ASp.net Web 表单应用程序。

我已根据这些 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" />

我试图从子 (Web Api2) 应用程序中的父应用程序中选择会话 saved/shared 的代码。

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" 应该保存父设置的会话值,但会话本身为空。

当我们在 API 中启用会话时,会话不为空,但父应用程序的值不可用。

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

我的目标是访问 "Parent Web Site" 设置的会话变量到 "Child Web Api 2 App",请帮忙。

我找到了解决问题的方法!

会话必须在 AcquireRequestState 事件之前启用,即

 protected void Application_PostMapRequestHandler(object sender, EventArgs e)
    {
        System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
    }