एसीएल: सही समाधान की तलाश में

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

अधिकारों के पृथक्करण की प्रणाली का विकास


आमतौर पर, अधिकारों का पृथक्करण इस तरह विकसित होता है:

पहले उपयोगकर्ता तालिका में व्यवस्थापक ध्वज बनाएँ।

फिर यह पता चलता है कि एडमीन्स के अलावा अन्य प्रकार के उपयोगकर्ता हैं। समूह (पूर्वनिर्धारित सेट) जोड़ें। अधिकार और समूह कसकर जुड़े हुए हैं। समूहों और उपयोगकर्ताओं के बीच संबंध कई में से एक है। ऐसा अक्सर होता है क्योंकि अधिकारों का पृथक्करण संगठनात्मक पदानुक्रम के साथ जुड़ा हुआ है।

इसके अलावा, अंत उपयोगकर्ता स्वयं समूह बनाना चाहते हैं और उन्हें अधिकार देना चाहते हैं।

अगला कदम यह है कि कुछ उपयोगकर्ताओं को अधिकारों की आवश्यकता होती है जो उनके समूह के दायरे से बाहर जाते हैं। ऐसे विकल्प हैं:


"अतिरिक्त" अधिकारों के साथ समस्या को हल करने के लिए, कभी-कभी वे समूहों को विरासत में लेते हैं। यह थोक संपादन के साथ समस्या छोड़ देता है। लेकिन अनुमति / निषेध संघर्षों को हल करने की समस्या है। उदाहरण के लिए: समूह ए में, कुछ कार्रवाई की अनुमति है, और समूह बी में, जो इसे विरासत में मिला है, वही कार्रवाई निषिद्ध है।

तकनीकी दृष्टिकोण से, एक रिलेशनल डेटाबेस में "ट्री-लाइक" संरचना के साथ काम करने में एक असहज क्षण है। उदाहरण के लिए, अधिकारों की सूची प्राप्त करने के लिए: पहले आपको सभी मूल समूहों को प्राप्त करना होगा, फिर आपको अधिकार तालिका में शामिल होने की आवश्यकता है। डेटाबेस से पूरी सूची प्राप्त करने के बाद, आपको इसके लिए संघर्ष समाधान नियम लागू करने की आवश्यकता होगी। MySQl कभी-कभी GROUP BY और ORDER के साथ इसके लिए "हैक" का उपयोग करता है, लेकिन यह समाधान पोर्टेबल नहीं है, क्योंकि इस तरह के GROUP BY व्यवहार SQL विनिर्देशन का अनुपालन नहीं करता है।

बेशक, ये हल करने योग्य समस्याएं हैं। आप यह पता लगा सकते हैं कि भूमिकाएँ कैसे रखें, संघर्ष कैसे हल करें। लेकिन क्या अंतिम उपयोगकर्ताओं के लिए इस तर्क को समझना आसान होगा?

इसके अलावा, सबसे अधिक संभावना है कि आपको कोड और डेटाबेस के बीच "सिंक्रनाइज़ेशन" की समस्या का सामना करना पड़ेगा। संपादन योग्य होने के अधिकारों के लिए - उन्हें डेटाबेस में संग्रहीत किया जाना चाहिए। लेकिन अधिकारों के पृथक्करण को क्रियान्वित करने के लिए जिम्मेदार कार्य कोड में संग्रहीत हैं।

कैसे करना है?


पहले से ही यह देख सकता है कि इसके बारे में क्या हो सकता है, हम निम्नलिखित निष्कर्ष निकाल सकते हैं:

तुरंत दो से अधिक समूहों (प्रवेश और गैर-व्यवस्थापक) की अपेक्षा के साथ अधिकारों के पृथक्करण की एक प्रणाली लिखें।

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

कई-से-कई अनुपात के साथ, "अतिरिक्त" अधिकार और समूह विरासत के साथ समस्या दूर हो जाती है। अतिरिक्त अधिकारों को अलग-अलग भूमिकाओं में रखा जाता है, जो "मुख्य" भूमिका को छोड़कर, उपयोगकर्ता में जोड़े जाते हैं।

संघर्ष के संकल्प को भी सरल बनाया गया है: चूंकि अधिकारों की संरचना "सपाट" है, इसलिए अधिकार स्वयं सरल होंगे। उदाहरण के लिए, ऐसे नियम हो सकते हैं:


कार्यान्वयन


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

बेस इंटरफ़ेस (बेस मॉड्यूल)


एसीएल को काम करने के लिए न्यूनतम आवश्यक।

सबसे बुनियादी फ़ंक्शन जो किसी भी एसीएल में होना चाहिए जो इस सवाल का जवाब देता है कि क्या इस उपयोगकर्ता को इस संसाधन के साथ कार्रवाई करने का अधिकार है:

  कर सकते हैं (उपयोगकर्ता, 'संपादित करें', संसाधन) # => सही / गलत

कंट्रोलर में कॉल करने का कार्य _ यह जाँचने के लिए कि क्या वर्तमान उपयोगकर्ता की पहुँच है। यह माना जाता है कि नियंत्रक वर्तमान उपयोगकर्ता (सीओसी) प्राप्त करने के लिए एक विधि प्रदान करता है।

  अधिकृत ('संपादित करें', संसाधन)

यदि कोई पहुंच नहीं है, तो नियंत्रण को अनधिकृत पहुंच त्रुटि हैंडलर में स्थानांतरित किया जाएगा। पीएल के आधार पर, यह अपवाद के माध्यम से या कॉलबैक के माध्यम से किया जा सकता है।

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

  AccessDenied को पकड़ें 
   रीडायरेक्ट
 अंत

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

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

  पता लगाएं (उपयोगकर्ता)
   अगर उपयोगकर्ता
     अनुमति ('सभी', 'पोस्ट')
   अन्यथा
     अनुमति ('पढ़ें', 'पोस्ट')
   अंत
 अंत

भूमिका मॉड्यूल


यह माना जाता है कि उपयोगकर्ता मॉडल उपयोगकर्ता भूमिकाओं (सीओसी) को प्राप्त करने के लिए एक विधि प्रदान करता है।
यदि समूहों को डेटाबेस में संग्रहीत करने की आवश्यकता नहीं है, तो अधिकार डीएसएल का उपयोग करके सेट किए जाते हैं।

  अनुमति ('व्यवस्थापक', 'सभी', 'पोस्ट')

मॉड्यूल को शामिल करें


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

 # लेख बना सकते हैं
 अनुमति ('लेखक', 'सृजन', 'पद')
 # सभी लेख देख सकते हैं मसौदा नहीं
 अनुमति ('लेखक', 'पढ़ा', 'पोस्ट [ड्राफ्ट = गलत]')
 # उनके लेख देख सकते हैं, संपादित कर सकते हैं, हटा सकते हैं
 अनुमति दें ('लेखक', ['पढ़ा', 'अपडेट', 'डिलीट'], 'पोस्ट [अपना]')

ऐसी विशेषताओं का समर्थन करने के लिए, आपको सहायक कार्यों (सहायकों) को लागू करने की आवश्यकता होगी। मॉडल उदाहरण (संसाधन) के साथ काम करने के लिए:

  खुद (उपयोगकर्ता, संसाधन)
   वापसी user.id == resource.user_id
 अंत

डेटाबेस से डेटा (सूची) प्राप्त करने की विधि के साथ काम करने के लिए।

  खुद_फिल्टर (उपयोगकर्ता, संसाधन_क्वेरी)
   वापसी resource_query.where ('user_id', user.id)
 अंत

मॉडल के लिए, आपको एक विधि लागू करने की आवश्यकता होगी जो आवश्यक कार्यों को कॉल करेगी। इस विधि का उपयोग कर इस तरह लग सकता है:

  Post.find ()। With_permissions ('पढ़ें', उपयोगकर्ता)

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

आप संसाधन के लिए एक से अधिक विशेषताओं को लागू कर सकते हैं, जबकि विशेषता शर्तों को तार्किक और के नियमों के अनुसार जोड़ना होगा।

आधार भंडारण


वर्णित संरचना डेटाबेस में आसानी से संग्रहीत होती है।

उपयोगकर्ता भूमिका - एन से एन; भूमिका, अधिकार - n से n; अधिकार, संसाधन - n से 1; अधिकार, गुण - n से n; कानून, कार्रवाई - n से 1;

प्रारंभिक मान सेट करना


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

अधिकार संपादन इंटरफ़ेस


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

अधिकार निर्माण / संपादन प्रपत्र


ऐसे क्षेत्र होने चाहिए:


और अधिकार इस तरह प्रदर्शित किए जाएंगे:

  <लेखक> <may / can> <edit> <खुद> <लेख>

तुल्यकालन


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

कोड से डेटा संग्रह


पहले आपको कोड पर सभी डेटा एकत्र करने की आवश्यकता है।

संसाधन जुटाना


संसाधन मॉडल या नियंत्रक हो सकते हैं (वे मार्ग या मार्ग भी हैं)। मॉडल को इकट्ठा करना आसान है, एमवीसी की विचारधारा के अनुसार उन्हें अलग से (एक अलग फ़ोल्डर में) स्थित होना चाहिए। मार्गों को इकट्ठा करते समय, कोई समस्या नहीं होनी चाहिए। आधुनिक एमवीसी ढांचे में, एक मार्ग को परिभाषित करना कुछ इस तरह दिखता है:

  प्राप्त करें ('/ पोस्ट /: आईडी', हैंडलर)

स्वाभाविक रूप से, आप अपनी आवश्यकताओं के आधार पर दोनों प्रकार के संसाधनों या केवल एक को इकट्ठा कर सकते हैं।

गुण संग्रह


यह करना भी काफी आसान है, क्योंकि विशेषताएँ एक निश्चित प्रकार के कार्य हैं जो एक निश्चित स्थान पर झूठ बोलते हैं। साथ ही, विशेषताओं के लिए, यह जानकारी रखना आवश्यक होगा कि वे किन मॉडलों के लिए उपयुक्त हैं।

क्रिया संग्रह


मॉडल (CRUD) के लिए 4 मानक क्रियाएं हैं और एक मार्ग (पहुंच) के लिए एक कार्रवाई है। अन्य सभी कार्यों को पाठ खोज (फ़ंक्शन अनुमति, प्राधिकृत, आदि) द्वारा कोड द्वारा खोजा जा सकता है।

कोड से डेटाबेस तक


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

अपडेट वितरित करते समय या सिस्टम को किसी अन्य हार्डवेयर (परिनियोजन) परिनियोजित करते समय, आपको सिंक्रनाइज़ेशन स्क्रिप्ट को चलाने की आवश्यकता होगी। स्क्रिप्ट फ़ाइल से डेटा पढ़ता है। यह जांच करेगा कि कोई संघर्ष नहीं है - डेटा जो अभी भी अधिकारों के पृथक्करण में शामिल है, हटाया नहीं गया है। फिर यह डेटाबेस में नया डेटा लिखेगा। अगला, डिफ़ॉल्ट रूप से नए अधिकार जोड़ें (यदि डिफ़ॉल्ट अधिकारों के साथ कोई अन्य फ़ाइल है)।

फ़ाइल प्रारूप


स्वचालित डेटा संग्रह के दौरान, "अतिरिक्त" डेटा जिसे संपादन इंटरफ़ेस में प्रदर्शित करने की आवश्यकता नहीं है (इसे डेटाबेस में जोड़ने की आवश्यकता नहीं है) फ़ाइल में गिर सकती है। ऐसे डेटा के लिए, आपको एक संकेत दर्ज करने की आवश्यकता है कि उन्हें डेटाबेस में संग्रहीत करने की आवश्यकता नहीं है (उदाहरण के लिए, विवरण के बजाय गलत)।

  {
   संसाधन: {
     "प्राप्त: / पोस्ट": गलत,
     "मॉडल: पोस्ट": "लेख",
     "अन्य"
   }
   विशेषताएं: {
     "अपना": {
       विवरण: "स्वयं",
       संसाधन: ["मॉडल: पोस्ट", "मॉडल: टिप्पणी"]
     }
   }
   क्रिया: {
     "संपादित करें": "संपादित करें",
     "प्रकाशित करें": {
       विवरण: "प्रकाशित करें",
       संसाधन: "मॉडल: पोस्ट",
       सच रखो
     }
   }
 }

छद्म-समूह, -सूत्र


सुविधा के लिए, आप इन psvedo समूहों को बना सकते हैं:

और ऐसा छद्म संसाधन:


अंतिम स्पर्श


हमें परीक्षण के लिए सहायकों को जोड़ना नहीं भूलना चाहिए।

लेख में क्या नहीं मिला


पढ़ना

विशेषताओं के रूप में मॉडल के क्षेत्र (पैरामीटर, गुण)


प्रारंभ में, मैं न केवल विशेषता कार्यों (सहायकों) को इकट्ठा करना चाहता था, बल्कि सभी मॉडल फ़ील्ड भी ताकि मैं उनकी तुलना कर सकूं (ड्राफ्ट = गलत, राशि> 100)। लेकिन मुझे एहसास हुआ कि यह एक अच्छा विचार नहीं है और यही कारण है:

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

इसलिए, मैंने मॉडल के क्षेत्रों के माध्यम से मूल्यों को स्थापित करने के विचार को छोड़ने का फैसला किया। यदि आपको ऐसा मूल्य निर्धारित करने की आवश्यकता है, तो आपको विशेषताओं के लिए सहायक लिखना होगा, अर्थात। ड्राफ्ट के लिए = सही / गलत आपको यह करने की आवश्यकता है:

  is_draft (उपयोगकर्ता, संसाधन)
   संसाधन वापस करें
 अंत
 is_not_draft (उपयोगकर्ता, संसाधन)
   वापसी!
 अंत

मॉडल क्षेत्र स्तर पर अधिकारों का पृथक्करण


यानी कुछ भूमिकाओं में केवल मॉडल के कुछ क्षेत्रों तक ही पहुँच होती है। मैंने इस प्रश्न को बाद के लिए छोड़ दिया (शायद दूसरे लेख के लिए)।


पुनश्च


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

एक लेख लिखते समय, मैंने यहाँ प्रेरणा की तलाश की:


युपीडी
उन्होंने टिप्पणियों का जवाब देना शुरू किया, कार्यान्वयन के बारे में सोचते हैं और तुरंत त्रुटियों को ढूंढते हैं:
हैंडलिंग में त्रुटि
1. मैंने संसाधनों के रूप में मार्गों का उपयोग करने का सुझाव दिया है, लेकिन वास्तव में, इस दृष्टिकोण से आप हल कर सकते हैं, केवल बहुत कम कार्य। यह लेख के पिछले संस्करण (ड्राफ्ट) से एक विचार है। हो सकता है कि यह शब्द मार्ग-आधारित acl से प्रेरित हो। या शायद REST (यह एक मृत अंत था) * * nix फ़ाइल सिस्टम अधिकार प्रणाली को खींचने का प्रयास करें।
तदनुसार, यहां यह पैराग्राफ है, कुछ नहीं के बारे में:
एक बार में सभी नियंत्रकों के लिए एक चेक सेट करना संभव होना चाहिए। प्रत्येक नियंत्रक में अधिकृत कॉल करने के लिए यह आवश्यक नहीं था। प्रौद्योगिकी के आधार पर, यह या तो कंट्रोलर के बेस क्लास में या मिडलवेयर का उपयोग करके किया जा सकता है।

इसके बजाय, आपको यह जांचने में सक्षम होना चाहिए कि प्रत्येक नियंत्रक में अधिकृत कॉल किया गया है। और अगर यह कहीं नहीं किया जाता है, तो एक अपवाद फेंक दें।
हर कंट्रोलर में ऑथराइज कॉल करना इतना मुश्किल है। क्लासिक रीस्ट के लिए स्थिति को कम किया जा सकता है, क्योंकि यह आसानी से सीआरयूडी मॉडल में बदल जाता है। आप मदद कर सकते हैं, लेकिन उन्हें कैसे बनाया जाए यह कार्यान्वयन और वाईपी पर निर्भर करता है।
** मैं लेख को ठीक करूंगा ** और मार्गों के विचार को संसाधनों के रूप में हटा दूंगा, लेकिन ऐतिहासिक संदर्भ के लिए मैं यहां सभी सुधारों की एक सूची छोड़ूंगा।
2. यह विचार भी नज़र रखने के लिए एक इंटरफ़ेस के बारे में आया जहां एक उपयोगकर्ता के पास यह अधिकार है और सभी उपयोगकर्ताओं / समूहों को खोजने के लिए एक इंटरफ़ेस है जिनके पास एक या दूसरा अधिकार है।
3. मुझे एहसास हुआ कि मैंने एमवीसी के ढांचे में इस समाधान के लाभों का खुलासा नहीं किया है। यह व्याख्या करना आवश्यक था कि, जबकि सभी तर्क एक ही स्थान पर संग्रहीत हैं, और पूरे आवेदन में एक पतली परत के साथ लिप्त नहीं है।

Source: https://habr.com/ru/post/In164807/


All Articles