उपयोगकर्ता अनुमति जाँच कहाँ और MVC में और किसके द्वारा होनी चाहिए?


26

क्या उपयोगकर्ता की अनुमति जांच मॉडल या नियंत्रक में होनी चाहिए? और कौन अनुमति चेक, उपयोगकर्ता वस्तु या कुछ उपयोगकर्ता प्रबंधन सहायक को संभालना चाहिए?

ऐसा कहां होना चाहिए?

नियंत्रक में जाँच:

class MyController {
  void performSomeAction() {
    if (user.hasRightPermissions()) {
      model.someAction();
    }
  }
  ...

नियंत्रक में जाँच होने से मॉडल को सरल क्रिया करने में मदद मिलती है, इसलिए हम कंट्रोलर को सभी तर्क दे सकते हैं।

मॉडल में जाँच:

class MyModel {
  void someAction() {
    if (user.hasRightPermissions()) {
      ...
    }
  }
  ...

मॉडल में चेक डालकर, हम मॉडल को जटिल करते हैं, लेकिन यह भी सुनिश्चित करते हैं कि हम गलती से उपयोगकर्ताओं को वे सामान नहीं करने देते हैं जो उन्हें नियंत्रक में नहीं करना चाहिए।

और किसके द्वारा?

एक बार जब हम जगह पर बस गए, तो चेक किसे करना चाहिए? उपभोक्ता?

Class User {
  bool hasPermissions(int permissionMask) {
    ...
  }
  ...

लेकिन यह वास्तव में उपयोगकर्ता की ज़िम्मेदारी नहीं है कि वह यह जान सके कि वह क्या कर सकता है?

Class UserManagement {
  bool hasPermissions(User user, int permissionMask) {
    ...
  }
  ...

मुझे पता है कि यह केवल एक सवाल पूछने के लिए आम है, ठीक है, एक सवाल है, लेकिन मुझे लगता है कि इनका उत्तर एक साथ दिया जा सकता है।

जवाबों:


20

हमेशा की तरह, "यह निर्भर करता है"

  • अनुमति जांच कार्यात्मक रूप से कहीं भी काम करेगी यह उन्हें डालने के लिए सुविधाजनक है,
  • लेकिन यदि आप एक तकनीकी प्रश्न पूछ रहे हैं, तो उत्तर 'चेक को प्रदर्शन करने के लिए आवश्यक डेटा का स्वामित्व करने वाली वस्तु में चेक डाल सकता है' (जो कि संभवतः नियंत्रक है)।
  • लेकिन अगर आप एक दार्शनिक प्रश्न पूछ रहे हैं, तो मैं एक वैकल्पिक उत्तर सुझाता हूं: उपयोगकर्ताओं को ऐसी क्रियाएं न दिखाएं जो उन्हें प्रदर्शन करने की अनुमति नहीं हैं

तो बाद के मामले में आपके पास बूलियन प्रॉपर्टी के रूप में कार्यान्वित कंट्रोलर में अनुमति की जांच हो सकती है, और उस प्रॉपर्टी को बटन या पैनल की विजिबल प्रॉपर्टी में यूजर-इंटरफेस में बाँध सकते हैं जो एक्शन को नियंत्रित करता है।

एक उपयोगकर्ता के रूप में, यह उन कार्यों के लिए बटन देखना निराशाजनक है जो मैं प्रदर्शन नहीं कर सकता; ऐसा लगता है कि मैं मज़े से रह रहा हूँ;)


हमारा आवेदन इस अपवाद के साथ तीसरे परिदृश्य को लागू करता है कि हम नियंत्रणों को छिपाते नहीं हैं, हम उन्हें अक्षम करते हैं। दुर्भाग्य से यह सब Winforms के पीछे-पीछे किया गया है, इसलिए यह वास्तव में OP प्रश्न के लिए प्रासंगिक नहीं है।
डेव नाय

11
"यह उन कार्यों के लिए बटन देखना निराशाजनक है जो मैं प्रदर्शन नहीं कर सकता" -> अपनी खुद की पोस्ट को उभारने की कोशिश करें :)
रोवन फ्रीमैन

5
यह केवल उन कार्यों के लिए बटन छिपाने के लिए पर्याप्त नहीं है जो उपयोगकर्ता प्रदर्शन नहीं कर सकता है, सर्वर को अनुमतियों के लिए प्रत्येक अनुरोध की जांच करनी चाहिए। तीसरा बुलेट आइटम "एक वैकल्पिक उत्तर" नहीं है, यह अनुमतियों के सर्वर-साइड के लिए जाँच के अलावा कुछ करना है।
फ्लिम

@ फ़ीलम ने सहमति व्यक्त की, यदि अनुरोधों को एक सर्वर द्वारा नियंत्रित किया जाता है; विशिष्ट प्रश्न नियंत्रक वर्ग
स्टीवन ए। लोव

7

सुरक्षा एक क्रॉस-कटिंग चिंता है, इसलिए इसे कई परतों में लागू करने की आवश्यकता है। एमवीसी के लिए उदाहरण निम्न है लेकिन अवधारणा अन्य आर्किटेक्चर और / या पैटर्न पर लागू होती है, आपको बस प्रवर्तन के बिंदुओं को पहचानना होगा।

ऐसा कहां होना चाहिए?

दृश्य में UI तत्व (विजेट्स, बटन, मेनू आदि) हो सकते हैं, जिन्हें उनकी अनुमति के आधार पर कुछ उपयोगकर्ताओं के लिए प्रदर्शित करने या न करने की आवश्यकता होती है। यह दृश्य इंजन की एक ज़िम्मेदारी हो सकती है , क्योंकि आप नहीं चाहते कि प्रत्येक दृश्य अपने आप इसे संभाल सके। उन तत्वों के प्रकार के आधार पर, जो आप कोल्ड पर अधिकृत कर रहे हैं, इस जिम्मेदारी को दूसरी जगह ले जाएं। उदाहरण के लिए, एक मेनू के बारे में सोचें जिसमें कुछ वस्तुओं को प्रदर्शित किया जाना है और कुछ नहीं। वस्तुओं को कहीं सूची के रूप में लागू किया जा सकता है और अनुमतियों के आधार पर उस सूची को फ़िल्टर किया जा सकता है फिर इसे दृश्य में अग्रेषित करें।

नियंत्रक अनुरोधों का जवाब देते हैं, इसलिए यदि किसी उपयोगकर्ता के पास कार्रवाई को लागू करने से पहले इसकी जांच करने की अनुमति नहीं है, तो नियंत्रक को रखने के बजाय जिम्मेदारी को कार्रवाई के चालान पर ले जाना चाहिए। यह आपके नियंत्रक को साफ रखने का लाभ है और यदि उन परिवर्तनों को लागू करने के लिए आपको अपने नियंत्रकों के माध्यम से झारना नहीं है, तो अनुमतियों में कुछ परिवर्तन करना होगा।

अनुमतियों के आधार पर संसाधन प्रदर्शित किए जाते हैं। यह सामान्य रूप से डेटाबेस स्तर पर किया जाता है, क्योंकि आप डेटाबेस से सब कुछ नहीं खींचना चाहते हैं और फिर अनुमतियाँ लागू करते हैं।

जैसा कि आप देख सकते हैं, जो आप अधिकृत करना चाहते हैं उसके आधार पर विभिन्न स्थान हैं जहां यह किया जाना चाहिए। लक्ष्य जितना संभव हो उतना विनीत होना है, ताकि जब आपकी सुरक्षा नीति बदल जाए तो आप इसे आसानी से लागू कर सकें, अधिमानतः आपके आवेदन के कोड में बदलाव किए बिना। यह छोटे अनुप्रयोगों के लिए मान्य नहीं हो सकता है, जहां अनुमति सेट काफी छोटा है और बहुत बार नहीं बदलता है। उद्यम अनुप्रयोगों में, हालांकि कहानी काफी अलग है।

किसको करना चाहिए?

स्पष्ट रूप से मॉडल नहीं। प्रत्येक परत में एक प्रवर्तन बिंदु होना चाहिए जो प्राधिकरण को संभालता है। ऊपर दिया गया इटैलिक पाठ प्रत्येक स्तर के लिए संभावित प्रवर्तन बिंदु पर प्रकाश डालता है।

XACML पर एक नजर । आपको इसे लागू करने की आवश्यकता नहीं है, लेकिन यह आपको कुछ दिशा-निर्देश देगा जिनका आप पालन कर सकते हैं।


यह सबसे अच्छा जवाब है। किसी कारण से शीर्ष एक और अन्य नियंत्रक और दृश्य, या दृश्य और मॉडल के बीच के अंतर से निपटते हैं, जो कि ओपी पूछ नहीं रहा है। धन्यवाद!
RedFur

1

मैं निम्नलिखित योजना का उपयोग करता हूं। यह कहने योग्य है कि अधिकांश उपयोगकर्ता अनुमतियों की जाँच को दो सामान्य मामलों में विभाजित किया जा सकता है:

  • पैरामीटर कार्रवाई की जाँच किए बिना उपयोगकर्ता की भूमिका के आधार पर नियंत्रक कार्रवाई के लिए उपयोगकर्ता का उपयोग कहा जाता है,
  • किसी भी तर्क या विशेष उपयोगकर्ता और विशेष मॉडल के बीच संबंधों के आधार पर उपयोगकर्ता की पहुंच।

विशेषताओं की जांच के बिना नियंत्रक कार्रवाई तक पहुंच आमतौर पर एमवीसी रूपरेखाओं में लागू की जाती है। यह बिल्कुल सरल है: आप नियमों को परिभाषित करते हैं, आपके उपयोगकर्ताओं की भूमिका है। आप बस जाँचते हैं कि उपयोगकर्ता को नियमों में अपनी भूमिका देखने की अनुमति है।

विशेष मॉडल में उपयोगकर्ता की पहुंच को मॉडल में परिभाषित किया जाना चाहिए। (अभिनेता आधार उपयोगकर्ता वर्ग है। मान लीजिए कि यह ग्राहक, विक्रेता या अतिथि हो सकता है।)

interface ICheckAccess
{
    public function checkAccess(Actor $actor, $role);
}

class SomeModel implements ICheckAccess
{
    public function checkAccess(Actor $actor, $role)
    {
        // Your permissions logic can be as sophisticated as you want.
    }
}

उस तर्क को मॉडल में रखने से कुछ लाभ होता है। एक्सेस चेक विधि विरासत में मिल सकती है, आपको किसी भी अतिरिक्त कक्षाएं बनाने की आवश्यकता नहीं है, आप सामान्य ओओपी लाभों का उपयोग कर सकते हैं।

अगला, एक्सेस चेकिंग को आसान बनाने के लिए, हम कुछ अनुमान लगाते हैं जो लगभग हमेशा सादगी और अच्छी शैली के लिए लागू होते हैं:

  • आमतौर पर नियंत्रक कुछ मॉडल वर्ग से संबंधित होते हैं;
  • कार्रवाई जो एक्सेस के लिए जाँच की जाती है, सिंगल मॉडल आईडी को पैरामीटर के रूप में लेती है;
  • इस पैरामीटर को हमेशा बेस कंट्रोलर क्लास की विधि से समान रूप से एक्सेस किया जा सकता है;
  • एक्शन को मॉडल के अनुरूप कंट्रोलर में रखा जाता है जो आईडी एक्शन लेता है।

इन मान्यताओं के साथ, मॉडल आईडी का उपयोग करने वाले कार्यों को विशेष मॉडल उदाहरण के साथ जोड़ा जा सकता है। वास्तव में, अधिकांश कार्यों को आसानी से रूपांतरित किया जा सकता है और ऊपर बताई गई मान्यताओं में फिट किया जा सकता है।

फिर, कुछ आधार सार नियंत्रक वर्ग को परिभाषित और विरासत में लिया जाना चाहिए।

abstract class ModelController
{
    // Retrieve model from database using id from action parameter.
    public abstract function loadModel($id);

    // Returns rules for user role to pass to SomeModel::checkAccess()
    // Something like array('view' => 'viewer', 'delete' => 'owner', 'update' => 'owner')
    public abstract function modelRules();

    public abstract fucntion getIdParameter();

    public function filterModelAccess()
    {
        $id = $this->getIdParameter();
        if(!$this->checkModelAccess($id))
            throw new HttpException(403);
    }

    public function checkModelAccess($id)
    {
        $model = $this->loadModel($id);
        $actor = My::app()->getActor();
        $rules = $this->modelRules();
        $role = $rules[My::app()->getActionName()];
        return $model->chechAccess($actor, $role);
    }
}

जब आप अपने मेनू का निर्माण करते हैं और कुछ लिंक दिखाने का निर्णय लेते हैं, तो आप SomeController :: checkModelAccess ($ id) विधि को कॉल कर सकते हैं।


मुझे PHP के लिए खेद है।
जॉर्ज सोवेतोव

1

मॉडल और दृश्य दोनों में

व्यू में - क्योंकि यूआई को यूआई-तत्वों को नहीं दिखाना चाहिए जो वर्तमान उपयोगकर्ता के लिए प्रतिबंधित हैं

(जैसे, कहते हैं, "हटाएं" बटन को उचित अनुमति वाले लोगों को दिखाया जाना चाहिए)

मॉडल में - क्योंकि आपके ऐप में शायद किसी तरह का एपीआई है, है ना? एपीआई को अनुमतियों की जांच करनी होगी और शायद मॉडल का फिर से उपयोग करना होगा।

(जैसे, कहते हैं, आपके पास UI में "हटाएं" बटन और उसी समय "http: / server / API / DeleteEntry / 123" एपीआई विधि है


आपने नियंत्रक पर मॉडल क्यों चुना?
फ्लिम

निश्चित नहीं है कि नियंत्रक में दृश्य, मॉडल और क्यों नहीं, जहां यह किया जाता है।
वी.पी.

@VP नियंत्रक के पास UI तत्वों को दिखाने / छुपाने की कोई शक्ति नहीं है (दृश्य से बूल-वार पास करने के अलावा)
jitbit

मुझे नहीं पता, हर जगह सामान्य रूप से नियंत्रक परत में किया जाता है, इसलिए मैं उत्सुक था।
वी.पी.

0

MVC एक प्रस्तुति पैटर्न है। इस तरह के दृश्य और नियंत्रक के पास केवल प्रस्तुति के संबंध में जिम्मेदारियां होनी चाहिए। कुछ अनुमतियाँ प्रस्तुति पर लागू होती हैं, जैसे विशेषज्ञ मोड, प्रयोगात्मक UI सुविधाएँ या विभिन्न डिज़ाइन। जिन्हें MVC- कंट्रोलर द्वारा नियंत्रित किया जा सकता है।

कई अन्य प्रकार की अनुमतियां एप्लिकेशन की कई परतों पर प्रासंगिक हैं। उदाहरण के लिए यदि आप ऐसे उपयोगकर्ता रखना चाहते हैं जो केवल डेटा देख सकते हैं और चीजें नहीं बदल सकते हैं:

  • प्रस्तुति परत को संपादन सुविधाओं को छिपाना है
  • यदि संपादन सुविधा को वैसे भी कहा जाता है, तो इसका पता लगाया जा सकता है / इसका पता लगाना चाहिए (व्यावसायिक स्तर के विशिष्ट भागों से, न कि डोमेन के विशिष्ट भाग से - ट्रेनडिटर, ट्रेन से नहीं) और संभवत: इसका अपवाद हो सकता है
  • डेटा एक्सेस लेयर भी लिखने के लिए जाँच कर सकता है, लेकिन अधिक जटिल प्रकार की अनुमतियों के लिए जो जल्दी से एक अच्छा विचार होने के लिए बिजनेस-लेयर के बहुत अधिक ज्ञान की आवश्यकता होती है।

इस दृष्टिकोण में कुछ दोहराव है। लेकिन जैसा कि प्रस्तुति आमतौर पर अस्थिर होती है, व्यक्ति आवेदन के आम तौर पर अधिक स्थिर हिस्से में अनुमति की जांच के लिए एक अच्छा मामला बना सकता है, भले ही इसका मतलब यह हो कि प्रस्तुति परत उद्देश्य के अनुसार काम करती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.