هل يمكنني وضع معرف جلسة ASP.Net في حقل نموذج مخفي؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

أنا أستخدم Yahoo Uploader، وهو جزء من مكتبة Yahoo UI، على موقع الويب الخاص بي ASP.Net للسماح للمستخدمين بتحميل الملفات.بالنسبة لأولئك غير المألوفين، يعمل برنامج التحميل باستخدام برنامج Flash الصغير ليمنحني المزيد من التحكم في مربع حوار FileOpen.يمكنني تحديد مرشح لأنواع الملفات، والسماح بتحديد ملفات متعددة، وما إلى ذلك.إنه أمر رائع، لكن به القيود الموثقة التالية:

بسبب خطأ معروف في Flash، لا يرسل برنامج التحميل الذي يعمل في Firefox في Windows ملفات تعريف الارتباط الصحيحة مع التحميل؛فبدلاً من إرسال ملفات تعريف الارتباط الخاصة بـ Firefox، فإنه يرسل ملفات تعريف الارتباط الخاصة بـ Internet Explorer للمجال المعني.كحل بديل، نقترح إما استخدام طريقة تحميل بدون ملفات تعريف الارتباط أو إلحاق document.cookie بطلب التحميل.

لذلك، إذا كان المستخدم يستخدم Firefox، فلا يمكنني الاعتماد على ملفات تعريف الارتباط لاستمرار الجلسة عند تحميل ملف.أحتاج إلى جلستهم لأنني أريد أن أعرف من هم!كحل بديل، أستخدم كائن التطبيق على النحو التالي:

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

لذلك، أقوم بإنشاء معرف فريد واستخدامه كمفتاح لتخزين Page.User كائن في نطاق التطبيق.أقوم بتضمين هذا المعرف كمتغير في POST عند تحميل الملف.بعد ذلك، في المعالج الذي يقبل تحميل الملف، أقوم بإمساك كائن المستخدم على النحو التالي:

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

هذا يعمل بالفعل، ولكن له عيبين صارخين:

  • إذا تمت إعادة تشغيل IIS أو تجمع التطبيقات أو حتى التطبيق فقط بين الوقت الذي يزور فيه المستخدم صفحة التحميل، ويقوم بالفعل بتحميل ملف، فسيتم حذف "uploadid" الخاص به من نطاق التطبيق ويفشل التحميل لأنني لا أستطيع مصادقته .

  • إذا قمت بالتوسع إلى سيناريو مزرعة الويب (وربما حتى حديقة الويب)، فسوف ينقطع هذا تمامًا.ربما لا أشعر بالقلق، إلا أنني أخطط لتوسيع نطاق هذا التطبيق في المستقبل.

هل لدى أي شخص طريقة أفضل؟هل هناك طريقة بالنسبة لي لتمرير معرف جلسة ASP.Net الفعلي في متغير POST، ثم استخدام هذا المعرف في الطرف الآخر لاسترداد الجلسة؟

أعلم أنه يمكنني الحصول على معرف الجلسة من خلاله Session.SessionID, وأعرف كيفية استخدام YUI لنشره على الصفحة التالية.ما لا أعرفه هو كيفية استخدام ذلك SessionID للاستيلاء على الجلسة من خادم الدولة.

نعم، أنا أستخدم خادم حالة لتخزين الجلسات، بحيث تستمر في إعادة تشغيل التطبيق/IIS، وستعمل في سيناريو مزرعة الويب.

هل كانت مفيدة؟

المحلول

هنا هي مشاركة من المشرف على تحميل SWFU والذي يشرح كيفية تحميل الجلسة من المعرف المخزن في Request.Form.أتصور أن نفس الشيء سيعمل مع مكون Yahoo.

لاحظ إخلاء المسؤولية الأمنية في أسفل المنشور.


من خلال تضمين ملف Global.asax والتعليمة البرمجية التالية، يمكنك تجاوز ملف تعريف ارتباط معرف الجلسة المفقود:

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.

إنها مجرد نتيجة، لذا نأمل ألا تواجه أي مشكلات في القياس.مشاكل أمنية رغم ذلك، لا أعرف.

يعتمد على هذا بلوق وظيفة, ، إليك وظيفة من المفترض أن توفر لك الجلسة لأي مستخدم بناءً على معرف الجلسة، على الرغم من أنها ليست جميلة:

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top