كيفية طرح استثناء إعلامي من AccessDecisionManager الذي يستخدم الناخبين

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

سؤال

لدي الحالة التالية:يتم تنفيذ آلية ترخيص طلبي باستخدام Spring Security.تنفذ الطبقة المركزية AccessDecisionManager ويستخدم الناخبين (كل منهم ينفذ AccessDecisionVoter) لتحديد ما إذا كان سيتم منح حق الوصول إلى طريقة ما أم لا.الخوارزمية التي تحسب الأصوات مخصصة:

public class PermissionManagerImpl extends AbstractAccessDecisionManager {

    public void decide(
            Authentication authentication,
            Object object,
            ConfigAttributeDefinition config) throws AccessDeniedException {
        Iterator<?> iter = getDecisionVoters().iterator();
        boolean wasDenied = false;

        while (iter.hasNext()) {
            AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
            int result = voter.vote(authentication, object, config);

            switch (result) {
                // Some tallying calculations
            }
        }

        if (wasDenied) {
            throw new AccessDeniedException("Access is denied");
        }               
    }

}

عند رفض الوصول إلى طريقة ما، يهتم عميل التطبيق بالحصول على استثناء إعلامي يحدد بالضبط لماذا تم رفض الوصول.وهذا يعني تمرير بعض المعلومات من الناخبين إلى مدير القرار.لسوء الحظ، فإن المعلومات الوحيدة هي المعيار AccessDecisionVoter يعد التمرير مرة أخرى إلى مدير القرار أحد قيم الإرجاع المحتملة (لقد تم منح الوصول, ACCESS_ABSTAIN أو تم الرفض).

ما هي أفضل طريقة للقيام بذلك؟

شكرًا.

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

المحلول

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

نظرًا لأنك تستخدم تطبيقاتك الخاصة لكل من الناخبين ومدير قرار الوصول، فلديك العديد من الخيارات المتاحة كما أراها:

  1. إرجاع قيم أخرى للأعداد الصحيحة كشكل من أشكال رمز الخطأ؛يعامل ACCESS_GRANTED, ACCESS_ABSTAIN و ACCESS_DENIED كقيمها النموذجية، ولكن تعامل مع أي عدد صحيح آخر على أنه "تم رفض الوصول" مع وجود رمز خطأ.من الأفضل أن يتوفر لديك جدول بحث لرموز الأخطاء - وهو في الأساس تعداد الرجل الفقير.
  2. ضمن ناخبك، ارجع ACCESS_DENIED كالمعتاد، وقم بتعيين بعض الخصائص التي يمكن الوصول إليها بشكل عام (إما على كائن الناخب نفسه أو ربما في بعض الحقول التي يمكن الوصول إليها بشكل ثابت) مع سبب الخطأ.في مديرك، إذا تم رفض وصول الناخب المخصص لديك، فتحقق من العقار للحصول على التفاصيل.
  3. كما هو مذكور أعلاه، قم بتعيين خاصية الخطأ داخل الناخب؛ولكن تأكد من أن مثيل Authentication إن تمريره هو أحد الفئات الفرعية المخصصة التي توفر موقعًا جيدًا لتعيين/استرداد هذه المعلومات.
  4. رمي AccessDeniedException (أو فئة فرعية مناسبة) من داخل ناخبك نفسه.وهذا ليس مثاليًا لأنه يفترض المنطق الموجود في مدير قرار الوصول؛ولكن يمكنك إما ترك هذه الفقاعة مستقيمة، أو إذا لزم الأمر، يمكنك الإمساك بها داخل المدير (ستكون الفئة الفرعية المخصصة مفيدة لهذا بالتأكيد) وإعادة طرحها إذا تم رفض الوصول بالفعل (شيء مشابه لما ProviderManager الطبقة تفعل معها lastException عامل).

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

نصائح أخرى

شكرا للأشخاص الذين أجابوا.

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

لقد رأيت نمطًا كهذا في أطر أخرى أيضًا.يتمتع هذا الحل بالمزايا التالية مقارنة بالحلول الممكنة الأخرى:

  • ويمكن للناخبين أن يظلوا عديمي الجنسية، وبالتالي يمكن أن يكونوا أفرادًا
  • يتم استخدام الواجهة القياسية لـ AccessDecisionVoter ولا تتم إضافة قيم إرجاع جديدة
  • يتم حفظ المعلومات الإضافية في كائن يتم تجاهله تلقائيًا لأنه لا أحد يستخدمه بعد AbstactDecisionManagerيقرر الطريقة، لذلك لا يلزم وجود رمز التنظيف

هتافات.

ألا تستطيع التنفيذ AccessDecisionManager مباشرة دون الاستعانة بالناخبين؟يمكنك بعد ذلك رمي AccessDeniedException بالمعلومات الصحيحة.ربما RoleVoters ليست التجريد الصحيح لاستخدامه في حالتك.

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