关于c#:是否可以将ASP.Net会话ID放在隐藏的表单字段中?

关于c#:是否可以将ASP.Net会话ID放在隐藏的表单字段中?

Can I put an ASP.Net session ID in a hidden form field?

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

Because of a known Flash bug, the Uploader running in Firefox in Windows does not send the correct cookies with the upload; instead of sending Firefox cookies, it sends Internet Explorer’s cookies for the respective domain. As a workaround, we suggest either using a cookieless upload method or appending document.cookie to the upload request.

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

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

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

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

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

  • 如果在用户访问上传页面并实际上传文件的时间之间重新启动了IIS,应用程序池甚至只是应用程序,则他们的" uploadid"将从应用程序范围中删除,并且上传失败,因为我无法对其进行身份验证。

  • 如果我曾经扩展到一个网络农场(甚至可能是一个网络花园)场景,那将完全被打破。我可能不会担心,除非我将来计划扩展此应用程序。

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

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

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


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

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

By including a Global.asax file and the following code you can override the missing Session ID cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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);
        }
    }
}

Security Warning: Don't just copy and paste this code in to your ASP.Net application without knowing what you are doing. It introduces security issues and possibilities of Cross-site Scripting.


依靠此博客文章,这是一个函数,该函数应根据会话ID为任何用户提供会话,尽管它并不美观:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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;
}

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

1
string sessionId = HttpContext.Current.Session.SessionID;

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

这只是个收获,因此希望您不会遇到任何扩展问题。我不知道有安全性问题。


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

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


推荐阅读