दिलचस्प पोस्ट
मैं पायथन में एक नेमस्पेस पैकेज कैसे बनाऊँ? कैसे JSN को IEnumerable <BaseType> में Newtonsoft JSON.NET के साथ करने के लिए क्या यह गैर-स्थिरता मानक पुस्तकालय कार्यों को constexpr के रूप में व्यवहार करने के लिए एक अनुरूप कम्पाइलर एक्सटेंशन है? इस गुंजाइश को एक्सेस सहेजें टेम्पलेट्स में एक त्रिगुट एक यूआरएल से विंडोज बैच फ़ाइल फाइल डाउनलोड करें JSON के लिए XSLT बराबर मैं csv के लिए 'for' लूप क्यों नहीं दोहरा सकता हूं। रीडर? (अजगर) ASP.NET में उपयोगकर्ता के क्लाइंट आईपी पते को कैसे प्राप्त करें? क्या मैं गैर मौजूदा सीएसएस वर्गों का उपयोग कर सकता हूँ? प्रश्न चिह्न "क्या है?" और बृहदान्त्र ":" ऑपरेटर के लिए उपयोग किया जाता है? फ़ायरबेज का उपयोग कर सर्वर साइड गणना आप समानता के लिए कार्य और समापन का परीक्षण कैसे करते हैं? वाइल्डकार्ड के कारण सूचियां सामान्य वूडू त्रुटि क्या GUID अद्वितीय समय का 100% है?

मैं अपने वेब एमवीसी अनुप्रयोग में एक एक्सेस कंट्रोल सूची कैसे लागू करूं?

पहला प्रश्न

कृपया, क्या आप मुझे बता सकते हैं कि एमवीसी में सबसे सरल एसीएल कैसे लगाया जा सकता है

नियंत्रक एसीएल का उपयोग करने का पहला तरीका यही है …

<?php class MyController extends Controller { public function myMethod() { //It is just abstract code $acl = new Acl(); $acl->setController('MyController'); $acl->setMethod('myMethod'); $acl->getRole(); if (!$acl->allowed()) die("You're not allowed to do it!"); ... } } ?> 

यह बहुत बुरा दृष्टिकोण है, और यह शून्य है कि हमें प्रत्येक नियंत्रक की विधि में एसीएल कोड जोड़ना होगा, लेकिन हमें किसी भी अतिरिक्त निर्भरता की आवश्यकता नहीं है!

अगले दृष्टिकोण सभी नियंत्रक के तरीकों को private और नियंत्रक की __call विधि में एसीएल कोड जोड़ने के लिए है।

 <?php class MyController extends Controller { private function myMethod() { ... } public function __call($name, $params) { //It is just abstract code $acl = new Acl(); $acl->setController(__CLASS__); $acl->setMethod($name); $acl->getRole(); if (!$acl->allowed()) die("You're not allowed to do it!"); ... } } ?> 

यह पिछले कोड के मुकाबले बेहतर है, लेकिन मुख्य कमियां हैं …

  • सभी नियंत्रक के तरीकों को निजी होना चाहिए
  • हमें प्रत्येक नियंत्रक की __call विधि में एसीएल कोड जोड़ना होगा।

अगला दृष्टिकोण माता पिता नियंत्रक में एसीएल कोड डालना है, लेकिन हमें अभी भी सभी बच्चे नियंत्रक के तरीकों को निजी रखने की आवश्यकता है

उपाय क्या है? और सबसे अच्छा अभ्यास क्या है? मुझे निष्पादित करने की विधि को अनुमति या अस्वीकार करने के निर्णय के लिए एसीएल फ़ंक्शन कहां चाहिए।

दूसरा सवाल

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

  • हमें यह सुनिश्चित करना होगा कि कहा जा रहा है कि विधि प्रोफ़ाइल है
  • हमें इस प्रोफ़ाइल के मालिक का पता लगाना होगा
  • हमें यह पता लगाना है कि दर्शक इस प्रोफ़ाइल का स्वामी है या नहीं
  • हमें इस प्रोफ़ाइल के बारे में प्रतिबंध नियम पढ़ना होगा
  • हमें प्रोफ़ाइल विधि निष्पादित करने या निष्पादित करने की आवश्यकता नहीं है

मुख्य प्रश्न प्रोफ़ाइल के मालिक का पता लगाने के बारे में है। हम यह पता लगा सकते हैं कि केवल मॉडल की विधि $ model-> getOwner () को निष्पादित करने वाले प्रोफाइल के मालिक कौन है, लेकिन एसीएल के पास मॉडल तक पहुंच नहीं है हम इसे कैसे लागू कर सकते हैं?

मुझे उम्मीद है कि मेरे विचार स्पष्ट हैं मेरी अंग्रेजी के लिए खेद है।

धन्यवाद।

वेब के समाधान से एकत्रित समाधान "मैं अपने वेब एमवीसी अनुप्रयोग में एक एक्सेस कंट्रोल सूची कैसे लागू करूं?"

प्रथम भाग / उत्तर (एसीएल कार्यान्वयन)

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

 class SecureContainer { protected $target = null; protected $acl = null; public function __construct( $target, $acl ) { $this->target = $target; $this->acl = $acl; } public function __call( $method, $arguments ) { if ( method_exists( $this->target, $method ) && $this->acl->isAllowed( get_class($this->target), $method ) ){ return call_user_func_array( array( $this->target, $method ), $arguments ); } } } 

और यह होगा कि आप इस प्रकार की संरचना का उपयोग कैसे करेंगे:

 // assuming that you have two objects already: $currentUser and $controller $acl = new AccessControlList( $currentUser ); $controller = new SecureContainer( $controller, $acl ); // you can execute all the methods you had in previous controller // only now they will be checked against ACL $controller->actionIndex(); 

जैसा कि आप देख सकते हैं, इस समाधान के कई फायदे हैं:

  1. किसी भी वस्तु पर रोकथाम का इस्तेमाल किया जा सकता है, न कि Controller उदाहरण
  2. प्राधिकरण के लिए जांच लक्ष्य ऑब्जेक्ट के बाहर होता है, जिसका अर्थ है कि:
    • मूल वस्तु एक्सेस नियंत्रण के लिए ज़िम्मेदार नहीं है, एसआरपी का पालन ​​करता है
    • जब आप "अनुमति अस्वीकृत" प्राप्त करते हैं, तो आप एक नियंत्रक के अंदर बंद नहीं होते हैं, अधिक विकल्प
  3. आप किसी भी अन्य ऑब्जेक्ट में यह सुरक्षित उदाहरण इंजेक्ट कर सकते हैं, यह सुरक्षा को बनाए रखेगा
  4. इसे लपेटो और इसे भूल जाओ .. आप दिखा सकते हैं कि यह मूल वस्तु है, यह एक ही प्रतिक्रिया होगी

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

दूसरा भाग / उत्तर (वस्तुओं के लिए आरबीएसी)

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

 $this->acl->isAllowed( get_class($this->target), $method ) 

मूल रूप से आपके पास दो विकल्प हैं:

  • प्रश्न में ऑब्जेक्ट के साथ एसीएल प्रदान करें लेकिन आपको डिमेटर के कानून का उल्लंघन करने के लिए सावधान रहना होगा:

     $this->acl->isAllowed( get_class($this->target), $method ) 
  • सभी प्रासंगिक विवरणों का अनुरोध करें और एसीएल को केवल इसकी जरूरत के मुताबिक प्रदान करें, जो इसे थोड़ा अधिक यूनिट-परीक्षण अनुकूल बना देगा:

     $command = array( get_class($this->target), $method ); /* -- snip -- */ $this->acl->isAllowed( $this->target->getPermissions(), $command ) 

युगल वीडियो जो आपको अपने स्वयं के कार्यान्वयन के साथ आने में मदद कर सकते हैं:

  • विरासत, बहुरूपता, और परीक्षण
  • चीजों के लिए मत देखो!

साइड नोट्स

आपको लगता है कि MVC में कौन सी मॉडल है, काफी सामान्य (और पूरी तरह से गलत) समझ है। मॉडल एक वर्ग नहीं है । यदि आपके पास FooBarModel नाम का वर्ग है या कुछ ऐसा है जो FooBarModel को संभालता है तो आप इसे गलत कर रहे हैं

उचित एमवीसी में मॉडल एक परत है, जिसमें कई कक्षाएं हैं। ज़िम्मेदारी के आधार पर कक्षाओं का बड़ा हिस्सा दो समूहों में अलग किया जा सकता है:

डोमेन बिजनेस लॉजिक

(और पढ़ें : यहां और यहां ):

कक्षाओं के इस समूह के उदाहरणों में मूल्यों की गणना, विभिन्न स्थितियों की जांच, बिक्री के नियमों को लागू करने और बाकी सभी को आप "व्यवसाय तर्क" कहेंगे। उनके पास कोई सुराग नहीं है कि डेटा कैसे संग्रहीत है, जहां यह संग्रहीत है या यहां तक ​​कि अगर भंडारण पहले स्थान पर मौजूद है।

डोमेन व्यापार ऑब्जेक्ट डेटाबेस पर निर्भर नहीं करते हैं जब आप एक चालान बना रहे हैं, तो इससे कोई फर्क नहीं पड़ता कि डेटा कहां से आता है। यह एसक्यूएल या रिमोट रिस्ट एपीआई से या तो एमएसडॉर्ड दस्तावेज़ के स्क्रीनशॉट का भी हो सकता है। व्यापार तर्क कोई बदलाव नहीं करता है।

डेटा एक्सेस और स्टोरेज

कक्षाओं के इस समूह से किए गए उदाहरणों को कभी-कभी डाटा एक्सेस ऑब्जेक्ट कहा जाता है आम तौर पर संरचनाएं जो डेटा मैपर पैटर्न को कार्यान्वित करती हैं (उसी नाम के ORM के साथ भ्रमित नहीं हैं .. कोई संबंध नहीं)। यह वह जगह है जहां आपके एसक्यूएल स्टेटमेंट्स (या शायद आपका डैमोकॉइड होगा, क्योंकि आप इसे एक्सएमएल में स्टोर करते हैं)।

दो प्रमुख भागों के बगल में, उदाहरणों / वर्गों का एक और समूह है, जिसका उल्लेख किया जाना चाहिए:

सेवाएं

यह वह जगह है जहां आपका और तृतीय पक्ष के घटक खेलने में आते हैं। उदाहरण के लिए, आप सेवा के रूप में "प्रमाणीकरण" के बारे में सोच सकते हैं, जिसे आपके द्वारा प्रदान किया जा सकता है, या कुछ बाहरी कोड इसके अलावा "मेल प्रेषक" एक सेवा होगी, जो एक PHPMailer या SwiftMailer या आपके स्वयं के मेल-प्रेषक घटक के साथ कुछ डोमेन ऑब्जेक्ट को एक साथ बुन कर सकता है

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

सेवाओं को बनाने के दौरान आपको क्या याद रखना चाहिए, यह है कि पूरी परत पतली होना चाहिए। सेवाओं में कोई व्यावसायिक तर्क नहीं है वे केवल डोमेन ऑब्जेक्ट, घटकों और मैपर को हथकंडा करने के लिए हैं।

इनमें से एक चीजों में से एक यह है कि सेवाओं को किसी भी प्रत्यक्ष तरीके से देखें परत पर असर नहीं पड़ेगा, और ऐसे हद तक स्वायत्त हैं, कि वे एमवीसी संरचना के बाहर ही इस्तेमाल किए जा सकते हैं (और अक्सर छोड़ दिया जाता है – हैं) इसके अलावा, इस तरह के आत्मनिर्धारित संरचनाएं सेवा और बाकी आवेदन के बीच बेहद कम युग्मन के कारण, एक अलग ढांचे / वास्तुकला के लिए माइग्रेशन को बहुत आसान बनाते हैं।

एसीएल और कंट्रोलर्स

सबसे पहले: ये अलग-अलग चीजें / परतें सबसे अधिक बार होती हैं जैसा कि आप अनुकरणीय नियंत्रक कोड की आलोचना करते हैं, यह दोनों एक साथ जोड़ता है – सबसे स्पष्ट रूप से बहुत तंग

tereško पहले से ही एक तरह से रेखांकित किया है कि आप डेकोरेटर पैटर्न के साथ यह और कैसे खत्म कर सकते हैं।

मैं पहली बार एक कदम पीछे जाना चाहता हूं कि आप जिस मूल समस्या का सामना कर रहे हैं उस पर गौर करें और उस पर थोड़ा चर्चा करें।

एक तरफ आप नियंत्रकों चाहते हैं कि वे जो काम (आज्ञा या कार्रवाई करने के लिए आज्ञा दी गई है, बस उसे आज्ञा कहें)।

दूसरी तरफ आप अपने आवेदन में एसीएल लगाने में सक्षम होना चाहते हैं। इन एसीएल के काम का क्षेत्र होना चाहिए – यदि मैं आपके प्रश्न को सही समझता हूं – अपने अनुप्रयोगों के कुछ निश्चित आदेशों तक पहुंच को नियंत्रित करने के लिए।

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

इस बात को संक्षेप में प्रस्तुत करते हैं कि हमारे पास क्या है:

  • आदेश
  • एसीएल
  • उपयोगकर्ता

ACL घटक यहां केंद्रीय है: कमांड के बारे में कम से कम कुछ जानने की आवश्यकता है (कमांड को सटीक मानने के लिए) और यह उपयोगकर्ता की पहचान करने में सक्षम होना चाहिए। आम तौर पर उपयोगकर्ताओं को आम तौर पर एक अद्वितीय आईडी द्वारा पहचाना जाता है लेकिन अक्सर वेबपॉलिकल में ऐसे उपयोगकर्ता होते हैं जो बिल्कुल भी नहीं पहचाने जाते हैं, जिसे अक्सर अतिथि, बेनामी, सबके इत्यादि कहते हैं। इस उदाहरण के लिए हम यह मानते हैं कि एसीएल एक उपयोगकर्ता ऑब्जेक्ट का उपभोग कर सकता है और इन विवरणों को समझा सकता है। उपयोगकर्ता ऑब्जेक्ट अनुप्रयोग अनुरोध ऑब्जेक्ट के लिए बाध्य है और एसीएल इसे उपभोग कर सकता है।

एक आदेश की पहचान करने के बारे में क्या? एमवीसी पैटर्न की आपकी व्याख्या बताती है कि कमांड एक क्लासनाम और एक विधि का नाम है। यदि हम अधिक बारीकी से देखते हैं तो एक आदेश के लिए भी तर्क (पैरामीटर) होते हैं। तो क्या यह पूछने के लिए मान्य है कि वास्तव में एक आदेश की पहचान की जाये? कक्षा नाम, विधि का नाम, संख्या या तर्कों के नाम, यहां तक ​​कि किसी भी तर्क या इन सबके मिश्रण का डेटा?

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

तो इन तीन हिस्सों (एसीएल, कमान और यूजर) एक दूसरे से संबंधित हैं, इस संदर्भ में अब और अधिक स्पष्ट है।

हम कह सकते हैं, एक काल्पनिक एसीएल संगत के साथ हम पहले से ही निम्न कार्य कर सकते हैं:

 $acl->commandAllowedForUser($command, $user); 

बस देखिए कि यहां क्या हो रहा है: दोनों कमांड और उपयोगकर्ता पहचानने योग्य बनाकर, एसीएल यह काम कर सकता है एसीएल का काम उपयोगकर्ता के उद्देश्य और ठोस कमान दोनों के काम से संबंधित नहीं है।

केवल एक हिस्सा गायब है, यह हवा में नहीं रह सकता है और यह नहीं है तो आपको उस स्थान का पता लगाने की आवश्यकता है जहां अभिगम नियंत्रण को किक करने की आवश्यकता है। चलिए मान लें कि मानक वेबपैक्शन में क्या होता है:

 User -> Browser -> Request (HTTP) -> Request (Command) -> Action (Command) -> Response (Command) -> Response(HTTP) -> Browser -> User 

उस जगह का पता लगाने के लिए, हम जानते हैं कि कंक्रीट कमांड निष्पादित होने से पहले होना चाहिए, इसलिए हम उस सूची को कम कर सकते हैं और केवल निम्नलिखित (संभावित) स्थानों की जांच करनी होगी:

 User -> Browser -> Request (HTTP) -> Request (Command) 

आपके आवेदन के कुछ बिंदु पर आपको पता है कि एक विशिष्ट उपयोगकर्ता ने कंक्रीट कमांड करने का अनुरोध किया है। आप पहले से ही किसी प्रकार की एसीएल कर रहे हैं: यदि कोई उपयोगकर्ता एक कमांड का अनुरोध करता है जो मौजूद नहीं है, तो आप उस आदेश को निष्पादित करने की अनुमति नहीं देते हैं। इसलिए जहां आपके आवेदन में ऐसा होता है, वह "वास्तविक" एसीएल चेक जोड़ने के लिए एक अच्छी जगह हो सकती है:

यह आदेश स्थित है और हम इसकी पहचान बना सकते हैं ताकि एसीएल इसके साथ निपट सकें। यदि उपयोगकर्ता के लिए कमांड की अनुमति नहीं है, तो कमांड निष्पादित नहीं किया जाएगा (कार्रवाई)। शायद CommandNotAllowedResponse के लिए CommandNotFoundResponse मामले के लिए कोई अनुरोध ठोस कमान पर हल नहीं किया जा सकता है।

एक जगह जहां एक ठोस HTTPRequest के मानचित्रण एक आदेश पर मैप किया जाता है अक्सर रूटिंग कहा जाता है। चूंकि रूटिंग के पास पहले से ही एक कमांड का पता लगाने की नौकरी है, इसलिए यह जांचने के लिए विस्तार क्यों नहीं करें कि कमांड वास्तव में प्रति एसीएल की अनुमति है? उदाहरण के लिए Router को एसीएल अवगत रूटर तक RouterACL : RouterACL यदि आपका राउटर User अभी तक नहीं जानता है, तो Router सही जगह नहीं है, क्योंकि एसीएल के लिए न सिर्फ कमांड काम करना है बल्कि यूजर को पहचानना होगा। तो यह जगह भिन्न हो सकती है, लेकिन मुझे यकीन है कि आप आसानी से उस स्थान का पता लगा सकते हैं जहां आपको विस्तारित करने की आवश्यकता है, क्योंकि यह वह स्थान है जो उपयोगकर्ता और आदेश की आवश्यकता को पूरा करता है:

 User -> Browser -> Request (HTTP) -> Request (Command) 

उपयोगकर्ता शुरुआत से ही उपलब्ध है, Request(Command) साथ पहले Request(Command)

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

तो सिर्फ चीजें अलग रखो जो एक-दूसरे के नहीं हैं एकल उत्तरदायित्व सिद्धांत (एसआरपी) के थोड़ा सा इस्तेमाल करने का उपयोग करें: कमांड को बदलने के लिए केवल एक ही कारण होना चाहिए – क्योंकि कमांड बदल गया है। इसलिए नहीं कि अब आप अपने आवेदन में एसीएल शुरू कर रहे हैं। इसलिए नहीं कि आप उपयोगकर्ता ऑब्जेक्ट स्विच करते हैं इसलिए नहीं कि आप किसी HTTP / HTML इंटरफ़ेस से SOAP या कमांड लाइन इंटरफ़ेस पर माइग्रेट करते हैं।

आपके केस में एसीएल कमांड में पहुंच को नियंत्रित करता है, कमांड में ही नहीं।

एक संभावना है कि आपके सभी नियंत्रकों को एक और वर्ग में लपेटें जो कि नियंत्रक तक फैली हुई है और प्राधिकृतता की जांच के बाद सभी फ़ंक्शन कॉल को लपेटे गए आवेश के लिए नियुक्त करता है।

आप इसे डिस्पैचर में अधिक अपस्ट्रीम भी कर सकते हैं (यदि आपका एप्लिकेशन वास्तव में एक है) और नियंत्रण विधियों के बजाय यूआरएल के आधार पर अनुमतियों को देखने के लिए।

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

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