我可以在隐藏的表单字段中放置ASP.Net会话ID吗?

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

由于已知的Flash错误,在Windows中的Firefox中运行的上传器不会通过上传发送正确的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”将从应用程序范围中删除,并且上载失败,因为我无法对它们进行身份validation。

  • 如果我扩展到Web场(可能甚至是Web园)场景,这将完全破坏。 我可能不会担心,除了我计划将来扩展这个应用程序。

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

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

是的,我正在使用状态服务器来存储会话,因此它们会持续应用程序/ IIS重新启动,并且可以在Web场方案中运行。

这是来自SWFUpload维护者的post,它解释了如何从存储在Request.Form中的ID加载会话。 我想同样的事情适用于雅虎组件。

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


通过包含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应用程序中,而不知道自己在做什么。 它介绍了跨站点脚本的安全问题和可能性。

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

 string sessionId = HttpContext.Current.Session.SessionID; 

然后你可以将它提供给隐藏的字段,然后通过YUI访问该值。

它只是一个获得,所以你希望不会有任何扩展问题。 但安全问题,我不知道。

依赖于这篇博客文章 ,这里有一个函数可以根据会话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; } 

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

但是,我认为如果应用程序重新启动,如果您不在sql server中存储会话 ,则sessionID将过期。