11 Stimmen

Kann ich eine ASP.Net-Sitzungs-ID in ein verstecktes Formularfeld eingeben?

Ich verwende den Yahoo Uploader, der Teil der Yahoo UI Library ist, auf meiner ASP.Net-Website, um Benutzern das Hochladen von Dateien zu ermöglichen. Für diejenigen, die damit nicht vertraut sind: Der Uploader arbeitet mit einem Flash-Applet, das mir mehr Kontrolle über den FileOpen-Dialog gibt. Ich kann einen Filter für Dateitypen festlegen, die Auswahl mehrerer Dateien zulassen usw. Das ist großartig, aber es hat die folgende dokumentierte Einschränkung:

Aufgrund eines bekannten Flash-Fehlers sendet der Uploader, der in Firefox unter Windows ausgeführt wird, nicht die richtigen Cookies mit dem Upload; statt der Firefox-Cookies werden die Cookies des Internet Explorers für die jeweilige Domäne gesendet. Als Abhilfe empfehlen wir, entweder eine Upload-Methode ohne Cookies zu verwenden oder die Datei document.cookie an die Upload-Anforderung anzuhängen.

Wenn also ein Benutzer Firefox verwendet, kann ich mich nicht auf Cookies verlassen, um seine Sitzung zu erhalten, wenn er eine Datei hochlädt. Ich brauche ihre Sitzung, weil ich wissen muss, wer sie sind! Als Workaround verwende ich das Application-Objekt folgendermaßen:

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

Ich erstelle also eine eindeutige ID und verwende sie als Schlüssel zum Speichern der Page.User Objekt im Anwendungsbereich. Ich füge diese ID als Variable in den POST ein, wenn die Datei hochgeladen wird. Im Handler, der den Datei-Upload akzeptiert, greife ich das User-Objekt folgendermaßen ab:

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

Das funktioniert tatsächlich, hat aber zwei eklatante Nachteile:

  • Wenn IIS, der App-Pool oder sogar nur die Anwendung zwischen der Zeit der Benutzer besucht die Upload-Seite neu gestartet wird, und tatsächlich eine Datei hochlädt, wird ihre "uploadid" aus Anwendungsbereich gelöscht und der Upload schlägt fehl, weil ich sie nicht authentifizieren kann.

  • Wenn ich jemals zu einer Web-Farm (möglicherweise sogar ein Web-Garten) Szenario skalieren, wird dies vollständig brechen. Ich könnte nicht besorgt sein, außer ich auf Skalierung dieser App in der Zukunft planen.

Hat jemand eine bessere Idee? Gibt es eine Möglichkeit für mich, die tatsächliche ASP.Net-Sitzungs-ID in einer POST-Variable zu übergeben und dann diese ID am anderen Ende zu verwenden, um die Sitzung abzurufen?

Ich weiß, dass ich die Sitzungs-ID über Session.SessionID und ich weiß, wie man YUI benutzt, um es auf der nächsten Seite zu veröffentlichen. Was ich nicht weiß, ist, wie man das benutzt SessionID um die Sitzung vom Statusserver zu übernehmen.

Ja, ich verwende einen Statusserver, um die Sitzungen zu speichern, so dass sie Anwendung/IIS-Neustarts überdauern und in einem Webfarm-Szenario funktionieren werden.

7voto

こちら ist ein Beitrag vom Betreuer von SWFUpload die erklärt, wie man die Sitzung aus einer in Request.Form gespeicherten ID lädt. Ich kann mir vorstellen, dass dasselbe auch für die Yahoo-Komponente funktionieren würde.

Beachten Sie die Sicherheitshinweise am Ende des Beitrags.


Durch Einfügen einer Global.asax-Datei und des folgenden Codes können Sie das fehlende Session-ID-Cookie außer Kraft setzen:

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);
        }
    }
}

Sicherheitswarnung: Kopieren Sie diesen Code nicht einfach und fügen Sie ihn in Ihre ASP.Net-Anwendung ein, ohne zu wissen, was Sie tun. Es führt zu Sicherheitsproblemen und der Möglichkeit des Cross-Site Scripting.

2voto

Pluto Punkte 2603

Verlassen Sie sich auf dieser Blogbeitrag Hier ist eine Funktion, die Ihnen die Sitzung für jeden Benutzer auf der Grundlage der Sitzungs-ID, obwohl es nicht schön ist:

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;
}

1voto

Seb Nilsson Punkte 25510

Sie können Ihre aktuelle SessionID mit dem folgenden Code abrufen:

string sessionId = HttpContext.Current.Session.SessionID;

Dann kann man das vielleicht in ein verstecktes Feld einspeisen und dann über YUI auf diesen Wert zugreifen.

Es ist nur ein Get, so dass Sie hoffentlich keine Skalierungsprobleme haben werden. Sicherheitsprobleme allerdings, die ich nicht kenne.

0voto

Espo Punkte 40386

Die ASP.Net-Session-ID wird gespeichert in Session.SessionID Sie könnten das also in ein verborgenes Feld eingeben und es dann auf der nächsten Seite veröffentlichen.

Ich denke jedoch, dass bei einem Neustart der Anwendung die SessionID abläuft, wenn Sie nicht Ihre Sitzungen im Sql-Server speichern .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X