2015-11-05 10 views
15

के साथ प्रमाणीकरण और अभिगम नियंत्रण फेसबुक की आधिकारिक रेखा यह है कि रिले "intentionally agnostic about authentication mechanisms" है। रिले भंडार में सभी उदाहरणों में, प्रमाणीकरण और अभिगम नियंत्रण एक अलग चिंता है। प्रैक्टिस में, मुझे इस अलगाव को लागू करने का एक आसान तरीका नहीं मिला है।रिले

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

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

मान लीजिए मैं जावास्क्रिप्ट में इस स्कीमा है:

export const Schema = new GraphQLSchema({ 
    query: new GraphQLObjectType({ 
     name: 'Query', 
     fields:() => ({ 
      node: nodeField, 
      user: { 
       type: new GraphQLObjectType({ 
        name: 'User', 
        args: { 
         // The `id` of the user being queried for 
         id: { type: new GraphQLNonNull(GraphQLID) }, 
         // Identity the user who is querying 
         session: { type: new GraphQLInputObjectType({ ... }) }, 
        }, 
        resolve: (_, { id, session }) => { 
         // Given `session, get user with `id` 
         return data.getUser({ id, session }); 
        } 
        fields:() => ({ 
         name: { 
          type: GraphQLString, 
          resolve: user => { 
           // Does `session` have access to this user's 
           // name? 
           user.name 
          } 
         } 
        }) 
       }) 
      } 
     }) 
    }) 
}); 

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

ऐसा लगता है कि ग्राफ के नीचे पहुंच ट्रिकल्स को नियंत्रित करने की आवश्यकता के रूप में जल्दी से जटिल हो जाता है।

इसके अलावा, मुझे nodeField जैसे प्रत्येक रूट क्वेरी के लिए एक्सेस को नियंत्रित करने की आवश्यकता है। मुझे यह सुनिश्चित करने की ज़रूरत है कि nodeInterface लागू करने वाले प्रत्येक नोड।

यह सब दोहराए जाने वाले काम की तरह लगता है। क्या इसे सरल बनाने के लिए कोई ज्ञात पैटर्न हैं? क्या मैं इस बारे में गलत तरीके से सोच रहा हूं?

+1

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

+1

क्या आपको कभी अच्छा उदाहरण/उत्तर मिला? मैं रिले के साथ टोकन प्रमाणीकरण (कोई सत्र) पर जानकारी की तलाश में हूं लेकिन –

+1

@ ग्रीनरेल कुछ भी नहीं ढूंढना मुश्किल है लेकिन मुझे पता चला कि इसे कैसे किया जाए। यह बहुत अच्छा है! असल में मेरे लिए कुंजी यह पता लगाना था कि आप चीजों को ग्राफक्लुएल "रूटवैल्यू" में डाल सकते हैं, जो संकल्प के सभी स्तरों पर उपलब्ध है। यदि आप एक्सप्रेस मिडलवेयर का उपयोग कर रहे हैं, तो ऐसा किया जाता है: https://gist.github.com/dminkovsky/3df6a8b0ebf6f14b2c10#file-gistfile1-txt-L143-L152। किसी भी कार्यान्वयन के लिए भी किया जा सकता है। फिर, नीचे दिए गए उत्तर के अनुसार, आप एसीएल में सहायता के लिए डेटा लोड करने के लिए 'दर्शक-उन्मुख' दृष्टिकोण भी ले सकते हैं। https://github.com/facebook/dataloader एक अच्छा सहायक उपकरण है। –

उत्तर

4

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

आप express-graphql मिडलवेयर का उपयोग कर रहे हैं, तो आप एक मिडलवेयर GraphQL मिडलवेयर पूर्ववर्ती में सत्र लोड और फिर GraphQL मिडलवेयर कॉन्फ़िगर जड़ मूल्य में है कि सत्र जगह कर सकते हैं:

function getSession(req, res, next) { 
    loadSession(req).then(session => { 
    req.session = session; 
    next(); 
    }).catch(
    res.sendStatus(400); 
); 
} 

app.use('/graphql', getSession, graphqlHTTP(({ session }) => ({ 
    schema: schema, 
    rootValue: { session } 
}))); 

इस सत्र है

new GraphQLObjectType({ 
    name: 'MyType', 
    fields: { 
    myField: { 
     type: GraphQLString, 
     resolve(parentValue, _, { rootValue: { session } }) { 
     // use `session` here 
     } 
    } 
    } 
}); 

आप अभिगम नियंत्रण प्राप्त करने के लिए "दर्शक" उन्मुख डेटा लोड के साथ इस जोड़ी कर सकते हैं: तो स्कीमा में किसी भी गहराई में उपलब्ध है। https://github.com/facebook/dataloader देखें जो इस प्रकार की डेटा लोडिंग ऑब्जेक्ट बनाने में मदद करता है और बैचिंग और कैशिंग प्रदान करता है।

function createLoaders(authToken) { 
    return { 
    users: new DataLoader(ids => genUsers(authToken, ids)), 
    cdnUrls: new DataLoader(rawUrls => genCdnUrls(authToken, rawUrls)), 
    stories: new DataLoader(keys => genStories(authToken, keys)), 
    }; 
} 
+0

आप इस दृष्टिकोण को आराम से कैसे ढूंढते हैं? –

+0

@ ग्रीनरेल मैं बहुत अनुभवी नहीं हूं। शायद कोई और इसका जवाब दे सकता है? –

7

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

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

एक ठोस उदाहरण में, मुझे कुछ उपयोगकर्ता को देखने की अनुमति नहीं दी जा सकती है, क्योंकि उसने मुझे अवरुद्ध कर दिया है। आपको उसे सामान्य रूप से देखने की अनुमति दी जा सकती है, लेकिन उसका कोई ईमेल नहीं, क्योंकि आप उसके साथ दोस्त नहीं हैं।

कोड में कुछ इस तरह:

var viewer = new Viewer(getLoggedInUser()); 
User.load(id, viewer).then(
    (user) => console.log("User name:", user.name), 
    (error) => console.log("User does not exist or you don't have access.") 
) 

GraphQL स्तर पर दृश्यता को लागू करने की कोशिश कर रहा है संभावित जानकारी लीक करने के लिए बहुत सारी है। फेसबुक के लिए GraphQL कार्यान्वयन में एक उपयोगकर्ता का उपयोग करने के कई रास्ते के बारे में सोचो:

node($userID) { name } 
node($postID) { author { name } } 
node($postID) { likers { name } } 
node($otherUserID) { friends { name } } 

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

+2

जोड़ा है यह एक गीथब रेपो इसे प्रदर्शित करना चाहिए। – MHK

+1

यह एक ठोस उदाहरण नहीं है। आपने थोड़े से एक्सेस कंट्रोल का जवाब दिया है (जो सिर्फ कुछ तर्क जोड़ रहा है) लेकिन प्रमाणीकरण को स्पर्श नहीं किया –

2

अगर किसी को भी इस विषय के साथ समस्या है: मैं dimadima के उत्तर के आधार पर रिले/GraphQL/एक्सप्रेस प्रमाणीकरण के लिए एक उदाहरण repo बनाया है। यह एक्सप्रेस मिडलवेयर और ग्राफ़क्लुएल उत्परिवर्तन

संबंधित मुद्दे