Question

J'utilise Yahoo Uploader, qui fait partie de la bibliothèque d'interface utilisateur Yahoo, sur mon site Web ASP.Net pour permettre aux utilisateurs de télécharger des fichiers.Pour ceux qui ne sont pas familiers, le programme de téléchargement utilise une applet Flash pour me donner plus de contrôle sur la boîte de dialogue FileOpen.Je peux spécifier un filtre pour les types de fichiers, autoriser la sélection de plusieurs fichiers, etc.C'est génial, mais il présente la limitation documentée suivante :

En raison d'un bug Flash connu, l'Uploader exécuté dans Firefox sous Windows n'envoie pas les bons cookies avec le téléchargement ;au lieu d'envoyer des cookies Firefox, il envoie les cookies d'Internet Explorer pour le domaine respectif.Pour contourner le problème, nous vous suggérons soit d'utiliser une méthode de téléchargement sans cookie, soit d'ajouter document.cookie à la demande de téléchargement.

Ainsi, si un utilisateur utilise Firefox, je ne peux pas compter sur les cookies pour conserver sa session lorsqu'il télécharge un fichier.J'ai besoin de leur séance parce que j'ai besoin de savoir qui ils sont !Pour contourner le problème, j'utilise l'objet Application ainsi :

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

Je crée donc un identifiant unique et je l'utilise comme clé pour stocker le Page.User objet dans le champ d’application de l’application.J'inclus cet ID en tant que variable dans le POST lorsque le fichier est téléchargé.Ensuite, dans le gestionnaire qui accepte le téléchargement du fichier, je récupère l'objet User ainsi :

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

Cela fonctionne réellement, mais présente deux inconvénients flagrants :

  • Si IIS, le pool d'applications ou même simplement l'application est redémarré entre le moment où l'utilisateur visite la page de téléchargement et télécharge réellement un fichier, son "ID de téléchargement" est supprimé de la portée de l'application et le téléchargement échoue car je ne peux pas les authentifier. .

  • Si jamais j'évolue vers un scénario de ferme Web (peut-être même un jardin Web), cela échouera complètement.Je ne suis peut-être pas inquiet, sauf que je prévois de faire évoluer cette application à l'avenir.

Quelqu'un a-t-il un meilleur moyen ?Existe-t-il un moyen pour moi de transmettre l'ID de session ASP.Net réel dans une variable POST, puis d'utiliser cet ID à l'autre extrémité pour récupérer la session ?

Je sais que je peux obtenir l'ID de session via Session.SessionID, et je sais comment utiliser YUI pour le publier sur la page suivante.Ce que je ne sais pas, c'est comment l'utiliser SessionID pour récupérer la session sur le serveur d'état.

Oui, j'utilise un serveur d'état pour stocker les sessions, afin qu'elles persistent lors des redémarrages d'application/IIS et fonctionnent dans un scénario de batterie de serveurs Web.

Était-ce utile?

La solution

Ici est un message du responsable de SWFTélécharger qui explique comment charger la session à partir d'un identifiant stocké dans Request.Form.J'imagine que la même chose fonctionnerait pour le composant Yahoo.

Notez les avertissements de sécurité au bas de l'article.


En incluant un fichier Global.asax et le code suivant, vous pouvez remplacer le cookie d'ID de session manquant :

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

Avertissement de sécurité: Ne vous contentez pas de copier et coller ce code dans votre application ASP.Net sans savoir ce que vous faites.Il introduit des problèmes de sécurité et des possibilités de Cross-site Scripting.

Autres conseils

Vous pouvez obtenir votre SessionID actuel à partir du code suivant :

string sessionId = HttpContext.Current.Session.SessionID;

Ensuite, vous pouvez peut-être insérer cela dans un champ caché, puis accéder à cette valeur via YUI.

C'est juste une chance, donc j'espère que vous n'aurez aucun problème de mise à l'échelle.Des problèmes de sécurité cependant, ça je ne sais pas.

Reposant sur ce billet de blog, voici une fonction qui devrait vous donner la session pour n'importe quel utilisateur en fonction de l'ID de session, même si ce n'est pas joli :

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

L'ID de session ASP.Net est stocké dans Session.SessionID afin que vous puissiez le définir dans un champ caché, puis le publier sur la page suivante.

Je pense cependant que si l'application redémarre, le sessionID expirera si vous ne le faites pas. stockez vos sessions sur le serveur SQL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top