【问题标题】:Can I put an ASP.Net session ID in a hidden form field?我可以将 ASP.Net 会话 ID 放在隐藏的表单字段中吗?
【发布时间】:2010-09-07 18:49:20
【问题描述】:

我在我的 ASP.Net 网站上使用 Yahoo Uploader(Yahoo UI 库的一部分)来允许用户上传文件。对于那些不熟悉的人,上传器通过使用 Flash 小程序让我更好地控制 FileOpen 对话框。我可以为文件类型指定过滤器,允许选择多个文件等。这很好,但它有以下记录的限制:

由于已知的 Flash 错误,在 Windows 的 Firefox 中运行的 Uploader 不会在上传时发送正确的 cookie;它不发送 Firefox cookie,而是发送相应域的 Internet Explorer cookie。作为一种解决方法,我们建议使用无 cookie 上传方法或将 document.cookie 附加到上传请求。

所以,如果用户使用的是 Firefox,我不能依靠 cookie 在他们上传文件时保持会话。我需要他们的会议,因为我需要知道他们是谁!作为一种解决方法,我正在使用 Application 对象:

Guid UploadID = Guid.NewGuid();
Application.Add(Guid.ToString(), User);

因此,我正在创建一个唯一 ID 并将其用作将 Page.User 对象存储在 Application 范围内的键。上传文件时,我将该 ID 作为变量包含在 POST 中。然后,在接受文件上传的处理程序中,我就这样抓取了 User 对象:

IPrincipal User = (IPrincipal)Application[Request.Form["uploadid"]];

这确实有效,但它有两个明显的缺点:

  • 如果 IIS、应用程序池,甚至只是应用程序在用户访问上传页面和实际上传文件之间重新启动,则它们的“uploadid”会从应用程序范围中删除,并且上传失败,因为我无法验证它们。

  • 如果我曾经扩展到网络农场(甚至可能是网络花园)场景,这将完全崩溃。我可能并不担心,但我确实计划在未来扩展这个应用程序。

有人有更好的方法吗?有没有办法让我在 POST 变量中传递实际的 ASP.Net 会话 ID,然后在另一端使用该 ID 来检索会话?

我知道我可以通过Session.SessionID 获取会话ID,并且我知道如何使用YUI 将其发布到下一页。我不知道如何使用 SessionID 从状态服务器获取会话。

是的,我使用状态服务器来存储会话,因此它们会持续应用程序/IIS 重新启动,并且可以在网络场场景中工作。

【问题讨论】:

    标签: c# asp.net session yui


    【解决方案1】:

    ASP.Net 会话 ID 存储在 Session.SessionID 中,因此您可以将其设置在隐藏字段中,然后将其发布到下一页。

    不过我认为,如果应用程序重新启动,如果你不store your sessions in sql server,sessionID 就会过期。

    【讨论】:

      【解决方案2】:

      您可以从以下代码中获取您当前的 SessionID:

      string sessionId = HttpContext.Current.Session.SessionID;
      

      然后您可以将其输入到隐藏字段中,然后通过 YUI 访问该值。

      这只是一个获取,因此希望您不会遇到任何缩放问题。安全问题,但我不知道。

      【讨论】:

        【解决方案3】:

        HereSWFUpload 的维护者的帖子,它解释了如何从存储在 Request.Form 中的 ID 加载会话。我想同样的事情也适用于 Yahoo 组件。

        请注意帖子底部的安全免责声明。


        通过包含 Global.asax 文件和以下代码,您可以覆盖丢失的会话 ID cookie:

        using System;
        using System.Web;
        
        public class Global_asax : System.Web.HttpApplication
        {
            private void Application_BeginRequest(object sender, EventArgs e)
            {
                /* 
                Fix for the Flash Player Cookie bug in Non-IE browsers.
                Since Flash Player always sends the IE cookies even in FireFox
                we have to bypass the cookies by sending the values as part of the POST or GET
                and overwrite the cookies with the passed in values.
        
                The theory is that at this point (BeginRequest) the cookies have not been ready by
                the Session and Authentication logic and if we update the cookies here we'll get our
                Session and Authentication restored correctly
                */
        
                HttpRequest request = HttpContext.Current.Request;
        
                try
                {
                    string sessionParamName = "ASPSESSID";
                    string sessionCookieName = "ASP.NET_SESSIONID";
        
                    string sessionValue = request.Form[sessionParamName] ?? request.QueryString[sessionParamName];
                    if (sessionValue != null)
                    {
                        UpdateCookie(sessionCookieName, sessionValue);
                    }
                }
                catch (Exception ex)
                {
                    // TODO: Add logging here.
                }
        
                try
                {
                    string authParamName = "AUTHID";
                    string authCookieName = FormsAuthentication.FormsCookieName;
        
                    string authValue = request.Form[authParamName] ?? request.QueryString[authParamName];
                    if (authValue != null)
                    {
                        UpdateCookie(authCookieName, authValue);
                    }
                }
                catch (Exception ex)
                {
                    // TODO: Add logging here.
                }
            }
        
            private void UpdateCookie(string cookieName, string cookieValue)
            {
                HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookieName);
                if (cookie == null)
                {
                    HttpCookie newCookie = new HttpCookie(cookieName, cookieValue);
                    Response.Cookies.Add(newCookie);
                }
                else
                {
                    cookie.Value = cookieValue;
                    HttpContext.Current.Request.Cookies.Set(cookie);
                }
            }
        }
        

        安全警告:不要在不知道自己在做什么的情况下将此代码复制并粘贴到您的 ASP.Net 应用程序中。它介绍了跨站点脚本的安全问题和可能性。

        【讨论】:

        • the wayback machine找到链接
        • @shamp00 如果您可以编辑答案以包含相关文本会有所帮助
        【解决方案4】:

        依靠this blog post,这是一个可以根据会话 ID 为任何用户获取会话的函数,尽管它并不漂亮:

        public SessionStateStoreData GetSessionById(string sessionId)
        {
            HttpApplication httpApplication = HttpContext.ApplicationInstance;
        
            // Black magic #1: getting to SessionStateModule
            HttpModuleCollection httpModuleCollection = httpApplication.Modules;
            SessionStateModule sessionHttpModule = httpModuleCollection["Session"] as SessionStateModule;
            if (sessionHttpModule == null)
            {
                // Couldn't find Session module
                return null;
            }
        
            // Black magic #2: getting to SessionStateStoreProviderBase through reflection
            FieldInfo fieldInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.NonPublic | BindingFlags.Instance);
            SessionStateStoreProviderBase sessionStateStoreProviderBase = fieldInfo.GetValue(sessionHttpModule) as SessionStateStoreProviderBase;
            if (sessionStateStoreProviderBase == null)
            {
                // Couldn't find sessionStateStoreProviderBase
                return null;
            }
        
            // Black magic #3: generating dummy HttpContext out of the thin air. sessionStateStoreProviderBase.GetItem in #4 needs it.
            SimpleWorkerRequest request = new SimpleWorkerRequest("dummy.html", null, new StringWriter());
            HttpContext context = new HttpContext(request);
        
            // Black magic #4: using sessionStateStoreProviderBase.GetItem to fetch the data from session with given Id.
            bool locked;
            TimeSpan lockAge;
            object lockId;
            SessionStateActions actions;
            SessionStateStoreData sessionStateStoreData = sessionStateStoreProviderBase.GetItem(
                context, sessionId, out locked, out lockAge, out lockId, out actions);
            return sessionStateStoreData;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-18
          • 2018-11-03
          • 2023-04-08
          • 2023-03-08
          • 1970-01-01
          相关资源
          最近更新 更多