asp.net-mvc-3 - شرح - asp net core ما هو




لماذا لا يمكنني الجمع بين[تخويل] و[أوتبركاش] سمات عند استخدام ذاكرة التخزين المؤقت أزور(.NET MVC3 التطبيق)؟ (2)

استخدام ويندوز أزور في Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider Web.DistributedCache.DistributedCacheOutputCacheProvider كموفر أوتبوتاكاش لتطبيق MVC3. وفيما يلي طريقة العمل ذات الصلة:

[ActionName("sample-cached-page")]
[OutputCache(Duration = 300, VaryByCustom = "User", 
    Location = OutputCacheLocation.Server)]
[Authorize(Users = "[email protected],[email protected]")]
public virtual ActionResult SampleCachedPage()
{
    return View();
}

أحصل على الاستثناء التالي عند تحميل هذا الملف الشخصي من متصفح ويب:

System.Configuration.Provider.ProviderException: When using a custom output cache provider like 'DistributedCache', only the following expiration policies and cache features are supported: file dependencies, absolute expirations, static validation callbacks and static substitution callbacks.

System.Configuration.Provider.ProviderException: When using a custom output cache provider like 'DistributedCache', only the following expiration policies and cache features are supported:  file dependencies, absolute expirations, static validation callbacks and static substitution callbacks.
   at System.Web.Caching.OutputCache.InsertResponse(String cachedVaryKey, CachedVary cachedVary, String rawResponseKey, CachedRawResponse rawResponse, CacheDependency dependencies, DateTime absExp, TimeSpan slidingExp)
   at System.Web.Caching.OutputCacheModule.OnLeave(Object source, EventArgs eventArgs)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

إذا قمت بإزالة السمة [أوثوريز]، يتم تخزين ذاكرة التخزين المؤقت كما هو متوقع. هل هذا يعني أنني لا يمكن وضع [أوتبوتسكاش] على طريقة عمل يجب أن يكون [تخويل]؟ أو، هل أحتاج إلى تجاوز أوثوريزاتريبوت باستخدام تطبيق مخصص يستخدم طريقة استدعاء التحقق من صحة ثابتة للذاكرة المؤقتة؟

تحديث 1

بعد إجابة إيفان، اختبرت طريقة العمل أعلاه في إيس إكسبريس (خارج أزور). هنا هو بلدي تجاوز الخاصية فاريبيكوستم = "المستخدم" على سمة أوتبركاش:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    return "User".Equals(custom, StringComparison.OrdinalIgnoreCase)
        ? Thread.CurrentPrincipal.Identity.Name
        : base.GetVaryByCustomString(context, custom);
}

عندما أزور الصفحة المخبأة في العينة ك [email protected]، يتم تخزين مخرجات الصفحة مؤقتا، ويعرض العرض "تم تخزين هذه الصفحة مؤقتا في 12/31/2011 11:06: 12 صباحا (أوتك)". إذا قمت بتسجيل الخروج ثم تسجيل الدخول باسم [email protected] وزيارة الصفحة، فإنه يعرض "تم تخزين هذه الصفحة في 12/31/2011 11:06: 38 صباحا (أوتك)". يؤدي تسجيل الدخول مرة أخرى ك [email protected] وإعادة النظر في الصفحة إلى ظهور ذاكرة التخزين المؤقت "تم تخزين هذه الصفحة مؤقتا في 12/31/2011 11:06: 12 صباحا (أوتك)" مرة أخرى. مزيد من تسجيل الدخول / خارج المحاولات تظهر أن الإخراج مختلفة يتم مؤقتا وإرجاع اعتمادا على المستخدم.

هذا يقودني إلى الاعتقاد بأن الإخراج يتم مؤقتا مؤقتا استنادا إلى المستخدم، الذي هو نية مع بلدي فاريبيكوستم = "المستخدم" الإعداد وتجاوز. المشكلة هي أنه لا يعمل مع موفر ذاكرة التخزين المؤقت توزيع أزور. إيفان، هل تجيب عن التخزين المؤقت فقط المحتوى العام لا تزال قائمة؟

التحديث 2

أنا حفر المصدر، ووجدت أن خارج أوثوريزاتريبوت خارج المربع في الواقع لديها استدعاء التحقق غير ثابت. هنا مقتطف من OnAuthorization :

if (AuthorizeCore(filterContext.HttpContext)) {
    // ** IMPORTANT **
    // Since we're performing authorization at the action level, the authorization code runs
    // after the output caching module. In the worst case this could allow an authorized user
    // to cause the page to be cached, then an unauthorized user would later be served the
    // cached page. We work around this by telling proxies not to cache the sensitive page,
    // then we hook our custom authorization code into the caching mechanism so that we have
    // the final say on whether a page should be served from the cache.

    HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
    cachePolicy.SetProxyMaxAge(new TimeSpan(0));
    cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else {
    HandleUnauthorizedRequest(filterContext);
}

CacheValidationHandler بتفويض التحقق من ذاكرة التخزين المؤقت إلى protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase) ، وهو بالطبع غير ثابت. أحد الأسباب لماذا ليست ثابتة هو لأنه، كما لوحظ في تعليق هام أعلاه، فإنه يستدعي protected virtual bool AuthorizeCore(HttpContextBase) .

من أجل القيام بأي من المنطق أوثورزيكور من أسلوب استدعاء التحقق من ذاكرة التخزين المؤقت ثابتة، فإنه يحتاج إلى معرفة خصائص المستخدمين والأدوار من مثيل أوثوريزاتريبوت. ومع ذلك هناك لا يبدو أن هناك طريقة سهلة لسد العجز. وأود أن تجاوز أونوثوريزاتيون لوضع هذه القيم 2 في هتبكونتيكست (عناصر جمع؟) ثم تجاوز أونكاشيتوريزاتيون للحصول عليها مرة أخرى. ولكن تلك الروائح القذرة.

إذا كنا حريصين على استخدام الخاصية فاريبيكوستم = "المستخدم" في السمة أوتبوتكاش، يمكننا تجاوز أونكاشيتوثوريزاتيون دائما العودة HttpValidationStatus.Valid؟ عندما لا يكون أسلوب العمل سمة أوتبوتكاش، ونحن لا داعي للقلق حول هذا الاستدعاء من أي وقت مضى يجري استدعاء، الصحيح؟ وإذا كان لدينا سمة أوتبوتسكاش دون فاريبيكوستم = "المستخدم"، ثم يجب أن يكون واضحا أن الصفحة يمكن أن ترجع أي نسخة مخبأة بغض النظر عن أي طلب المستخدم إنشاء النسخة المخبأة. ما مدى خطورة هذا؟


كنت الزيتون الصحيح. التخزين المؤقت يعمل عن طريق التخزين المؤقت للإخراج بأكمله من الإجراء (بما في ذلك جميع السمات) ثم إرجاع النتيجة إلى المكالمات اللاحقة دون استدعاء أي من التعليمات البرمجية الخاصة بك.

وبسبب هذا لا يمكنك تخزين ذاكرة التخزين المؤقت والتحقق من التفويض لأنه عن طريق التخزين المؤقت أنك لن ندعو أي من التعليمات البرمجية (بما في ذلك إذن). ولذلك يجب أن يكون أي شيء يتم تخزينه مؤقتا بشكل عام.


لقد عدت إلى هذه المسألة، وبعد قليل من ترقيع، استنتجت أنه لا يمكنك استخدام خارج منطقة الجزاء System.Web.Mvc.AuthorizeAttribute جنبا إلى جنب مع خارج منطقة الجزاء System.Web.Mvc.OutputCacheAttribute عند استخدام أزور ديستريبوتدكاش . السبب الرئيسي هو لأنه، كما تشير رسالة الخطأ في السؤال الأصلي، يجب أن تكون طريقة استدعاء التحقق من صحة ثابتة من أجل استخدامه مع أزور في ديستريبوتدكاش. طريقة استدعاء ذاكرة التخزين المؤقت في السمة مفك أوثوريز هو أسلوب مثيل.

ذهبت في محاولة لمعرفة كيفية جعله العمل عن طريق جعل نسخة من أوثوريزاتريبوت من مصدر مفك، إعادة تسميته، ربطه إلى عمل مع أوتبوتكاش متصلة أزور، والتصحيح. السبب في طريقة استدعاء ذاكرة التخزين المؤقت ليست ثابتة لأنه، من أجل المصادقة، السمة يحتاج إلى التحقق من المستخدم هتبكونتيكست ضد قيم الخاصية المستخدمين والأدوار التي يتم تعيينها عند إنشاء السمة. في ما يلي الرمز ذي الصلة:

OnAuthorization

public virtual void OnAuthorization(AuthorizationContext filterContext) {
    //... code to check argument and child action cache

    if (AuthorizeCore(filterContext.HttpContext)) {
        // Since we're performing authorization at the action level, 
        // the authorization code runs after the output caching module. 
        // In the worst case this could allow an authorized user
        // to cause the page to be cached, then an unauthorized user would 
        // later be served the cached page. We work around this by telling 
        // proxies not to cache the sensitive page, then we hook our custom
        // authorization code into the caching mechanism so that we have
        // the final say on whether a page should be served from the cache.

        HttpCachePolicyBase cachePolicy = filterContext
            .HttpContext.Response.Cache;
        cachePolicy.SetProxyMaxAge(new TimeSpan(0));
        cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
    }
    else {
        HandleUnauthorizedRequest(filterContext);
    }
}

استدعاء التحقق من ذاكرة التخزين المؤقت

private void CacheValidateHandler(HttpContext context, object data, 
    ref HttpValidationStatus validationStatus) {
    validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}

// This method must be thread-safe since it is called by the caching module.
protected virtual HttpValidationStatus OnCacheAuthorization
    (HttpContextBase httpContext) {
    if (httpContext == null) {
        throw new ArgumentNullException("httpContext");
    }

    bool isAuthorized = AuthorizeCore(httpContext);
    return (isAuthorized) 
        ? HttpValidationStatus.Valid 
        : HttpValidationStatus.IgnoreThisRequest;
}

كما ترون، استدعاء التحقق من ذاكرة التخزين المؤقت في نهاية المطاف استدعاء أوثوريزكور، وهو طريقة مثيل آخر (الظاهري المحمي). أوثوريزكور، الذي كان يسمى أيضا خلال أونوثوريزاتيون، لا 3 الأشياء الرئيسية:

  1. التحقق من أن HttpContextBase.User.Identity.IsAuthenticated == ترو

  2. إذا كانت السمة تحتوي على خاصية سلسلة المستخدمين غير فارغة، يتحقق من تطابق HttpContextBase.User.Identity.Name إحدى القيم المفصولة بفواصل.

  3. إذا كانت الخاصية المميزة تحتوي على خاصية سلسلة الأدوار غير الفارغة، تحقق من أن HttpContextBase.User.IsInRole لأحد القيم المفصولة بفواصل.

AuthorizeCore

// This method must be thread-safe since it is called by the thread-safe
// OnCacheAuthorization() method.
protected virtual bool AuthorizeCore(HttpContextBase httpContext) {
    if (httpContext == null) {
        throw new ArgumentNullException("httpContext");
    }

    IPrincipal user = httpContext.User;
    if (!user.Identity.IsAuthenticated) {
        return false;
    }

    if (_usersSplit.Length > 0 && !_usersSplit.Contains
        (user.Identity.Name, StringComparer.OrdinalIgnoreCase)) {
        return false;
    }

    if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) {
         return false;
    }

    return true;
}

عند محاولة ببساطة جعل أسلوب استدعاء التحقق من صحة ثابتة، لن يتم ترجمة التعليمات البرمجية لأنه يحتاج إلى الوصول إلى هذه الحقول _rolesSplit و _usersSplit، التي تستند إلى خصائص المستخدمين والأدوار العامة.

كانت المحاولة الأولى لتمرير هذه القيم إلى الاستدعاء باستخدام وسيطة object data من CacheValidateHandler . حتى بعد إدخال أساليب ثابتة، وهذا لا يزال لا يعمل، وأسفرت عن نفس الاستثناء. كنت آمل أن البيانات الكائن سيكون مسلسل، ثم مرت مرة أخرى إلى معالج التحقق من صحة أثناء الاستدعاء. على ما يبدو هذا ليس هو الحال، وعند محاولة القيام بذلك، أزور في ديستريبوتدكاش لا يزال يعتبر استدعاء غير ثابت، مما أدى إلى نفس الاستثناء والرسالة.

// this won't work
cachePolicy.AddValidationCallback(CacheValidateHandler, new object() /* data */);

كانت المحاولة الثانية لإضافة القيم إلى مجموعة HttpContext.Items ، حيث يتم تمرير مثيل HttpContext تلقائيا إلى المعالج. وهذا لم ينجح أيضا. و HttpContext التي يتم تمريرها إلى CacheValidateHandler ليست نفس المثيل الموجود على الخاصية filterContext.HttpContext . في الواقع، عندما ينفذ كاشيفاليداتهاندلر، لديه جلسة فارغة ودائما مجموعة فارغة البنود.

// this won't work
private void CacheValidateHandler(HttpContext context, object data, 
    ref HttpValidationStatus validationStatus) {
    Debug.Assert(!context.Items.Any()); // even after I put items into it
    validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}

ومع ذلك...

على الرغم من أنه يبدو أنه لا توجد وسيلة لتمرير قيم الخاصية "المستخدمين والأدوار" مرة أخرى إلى معالج استدعاء التحقق من ذاكرة التخزين المؤقت، HttpContext تمريرها إلى أنه في الواقع لديها المستخدم الرئيسي الصحيح . أيضا، أي من الإجراءات حيث أريد حاليا أن الجمع بين [أوثوريز] و [أوثركاش] تمرير أي وقت مضى المستخدمين أو الأدوار الخاصية إلى منشئ أوثوريزاتريبوت.

لذلك، فمن الممكن إنشاء User.Identity.IsAuthenticated == true مخصص الذي يتجاهل هذه الخصائص، وفحص فقط للتأكد من User.Identity.IsAuthenticated == true . إذا كنت بحاجة إلى مصادقة ضد دور معين، يمكنك أيضا القيام بذلك والجمع مع أوتبوتكاش ... ومع ذلك، سوف تحتاج إلى سمة مميزة لكل (مجموعة من) دور (ق) من أجل جعل طريقة استدعاء التحقق من ذاكرة التخزين المؤقت ثابت . وسوف أعود ونشر التعليمات البرمجية بعد لقد صقلت قليلا.