Могу ли я указать ASP.Идентификатор сетевого сеанса в скрытом поле формы?

StackOverflow https://stackoverflow.com/questions/43324

  •  09-06-2019
  •  | 
  •  

Вопрос

Я использую Yahoo Uploader, часть библиотеки пользовательского интерфейса Yahoo, на моем веб-сайте ASP.Net, чтобы позволить пользователям загружать файлы.Для тех, кто не знаком, программа загрузки работает с использованием флэш-апплета, чтобы дать мне больше контроля над диалогом открытия файла.Я могу указать фильтр для типов файлов, разрешить выбор нескольких файлов и т.д.Это здорово, но у него есть следующее документированное ограничение:

Из-за известной ошибки Flash Загрузчик, запущенный в Firefox в Windows, не отправляет правильные файлы cookie при загрузке;вместо отправки файлов cookie Firefox, он отправляет файлы cookie Internet Explorer для соответствующего домена.В качестве обходного пути мы предлагаем либо использовать метод загрузки без использования файлов cookie, либо добавлять document.cookie к запросу на загрузку.

Итак, если пользователь использует Firefox, я не могу полагаться на файлы cookie для сохранения их сеанса при загрузке файла.Мне нужен их сеанс, потому что мне нужно знать, кто они такие!В качестве обходного пути я использую объект Application таким образом:

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

Итак, я создаю уникальный идентификатор и использую его в качестве ключа для хранения Page.User объект в области применения.Я включаю этот идентификатор в качестве переменной в СООБЩЕНИЕ при загрузке файла.Затем в обработчике, который принимает загрузку файла, я таким образом захватываю объект User:

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

Это действительно работает, но у него есть два вопиющих недостатка:

  • Если IIS, пул приложений или даже просто приложение перезапускается в промежутке между посещением пользователем страницы загрузки и фактической загрузкой файла, их "uploadid" удаляется из области приложения, и загрузка завершается неудачно, потому что я не могу их аутентифицировать.

  • Если я когда-нибудь масштабируюсь до сценария веб-фермы (возможно, даже веб-сада), это полностью сломается.Возможно, я бы и не беспокоился, если бы не планировал масштабировать это приложение в будущем.

У кого-нибудь есть способ получше?Есть ли у меня способ передать фактический ASP.Чистый идентификатор сеанса в переменной POST, а затем использовать этот идентификатор на другом конце для извлечения сеанса?

Я знаю, что могу получить идентификатор сеанса через Session.SessionID, и я знаю, как использовать YUI, чтобы опубликовать его на следующей странице.Чего я не знаю, так это как это использовать SessionID чтобы перехватить сеанс с сервера состояния.

Да, я использую сервер состояния для хранения сеансов, поэтому они сохраняются при перезапуске приложения / IIS и будут работать в сценарии веб-фермы.

Это было полезно?

Решение

Здесь это сообщение от сопровождающего SWFUpload Загрузить в котором объясняется, как загрузить сеанс из идентификатора, хранящегося в Request.Form.Я предполагаю, что то же самое сработало бы и для компонента Yahoo.

Обратите внимание на заявления об отказе от ответственности в нижней части сообщения.


Включив глобальный файл.asax и следующий код, вы можете переопределить отсутствующий файл 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, не зная, что вы делаете.В нем рассказывается о проблемах безопасности и возможностях межсайтового скриптинга.

Другие советы

Вы можете получить свой текущий идентификатор сеанса из следующего кода:

string sessionId = HttpContext.Current.Session.SessionID;

Затем вы можете ввести это значение в скрытое поле, возможно, а затем получить доступ к этому значению через YUI.

Это просто get, так что, надеюсь, у вас не возникнет никаких проблем с масштабированием.Однако есть проблемы с безопасностью, о которых я не знаю.

Полагаясь на это сообщение в блоге, вот функция, которая должна предоставить вам сеанс для любого пользователя на основе идентификатора сеанса, хотя это и некрасиво:

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 Идентификатор сеанса хранится в Session.SessionID таким образом, вы могли бы указать это в скрытом поле, а затем опубликовать на следующей странице.

Однако я думаю, что если приложение перезапустится, срок действия идентификатора сеанса истечет, если вы этого не сделаете храните свои сеансы в sql server.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top