تشرين الأول (أكتوبر) 2008
مقدمة
الجمهور
ستوضّح لك هذه المقالة كيفية إنشاء أداة Blogger. ويفترض هذا الدليل أنّك على دراية بواجهات Google Data APIs ومكتبة برامج JavaScript. يجب أيضًا أن تكون بارعًا في JavaScript ولديك بعض الخبرة في تنفيذ أداة OpenSocial باستخدام gadgets.* API.
يوضّح هذا المثال أيضًا كيفية استخدام المكتبات الخارجية بنجاح في أدواتك. استخدمتُ jQuery (بشكل أساسي لتأثيرات واجهة المستخدم) وTinyMCE، وهو مكوّن إضافي رائع لمحرّر نصوص منسّقة WYSIWYG.
الحافز
لا يتطلّب إنشاء أداة تستخدم JSON مع إحدى واجهات Google Data API سوى القليل من JavaScript. إنّ المشكلة الرئيسية في هذه الأداة هي أنّ البيانات
متاحة للجميع ويمكن قراءتها فقط. لإنشاء أدوات أكثر إثارة للاهتمام، يجب أن يكون لديك إذن بالوصول إلى البيانات الخاصة بالمستخدم (وهو أمر يتطلّب المصادقة). حتى الآن، لم تكن هناك طريقة رائعة للاستفادة من واجهات برمجة التطبيقات لحساب Google. يتطلّب AuthSub عمليات إعادة توجيه المتصفّح، بينما يعرض ClientLogin بيانات اعتماد المستخدم من جهة العميل. حتى اختراق تطبيق مصغّر type="url"
كان أمرًا غير مريح.
أدخِل خادم وكيل OAuth.
خادم وكيل OAuth
إذا لم تكن على دراية ببروتوكول OAuth، فهو معيار مصادقة يتيح للمستخدم مشاركة بياناته الخاصة مع موقع إلكتروني أو أداة أخرى. تتطلّب مواصفات OAuth توقيع جميع طلبات البيانات رقميًا. هذا الإجراء رائع للأمان، ولكن في حالة أداة JavaScript، تكون إدارة المفاتيح الخاصة وإنشاء التواقيع الرقمية غير آمنة. هناك أيضًا التعقيد الإضافي للمشاكل المتعلّقة بالنطاقات المتعددة.
لحسن الحظ، يتم حلّ هذه المشاكل من خلال الاستفادة من ميزة في منصة الأدوات الصغيرة تُعرف باسم OAuth Proxy. تم تصميم OAuth Proxy لتسهيل عمل مطوّري الأدوات. يخفي هذا البروتوكول الكثير من تفاصيل المصادقة في OAuth ويتولّى تنفيذ المهام المعقّدة نيابةً عنك. يوقّع الخادم الوكيل على طلبات البيانات نيابةً عن أداتك، لذا لا داعي لإدارة المفاتيح الخاصة أو القلق بشأن توقيع الطلبات. إنّها تعمل ببساطة!
يستند خادم وكيل OAuth إلى مشروع مفتوح المصدر يُسمى Shindig، وهو تنفيذ لمواصفات الأداة.
ملاحظة: لا تتوفّر خدمة OAuth Proxy إلا للأدوات التي تستخدم واجهة برمجة التطبيقات gadgets.*
وتعمل في حاويات OpenSocial.
لا تتوافق مع واجهة برمجة التطبيقات القديمة للأدوات.
البدء
سيركّز الجزء المتبقي من هذا البرنامج التعليمي على إنشاء أداة للوصول إلى بيانات المستخدم على Blogger. سنشرح عملية المصادقة (باستخدام OAuth Proxy) باستخدام مكتبة برامج JavaScript، ثم سنشرح كيفية نشر مشاركة على Blogger.
المصادقة
أولاً، علينا إخبار الأداة باستخدام بروتوكول OAuth. لإجراء ذلك، أضِف العنصر <OAuth>
في القسم <ModulePrefs>
للأداة:
<ModulePrefs> ... <OAuth> <Service name="google"> <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.blogger.com/feeds/" method="GET" /> <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken? oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> </Service> </OAuth> ... </ModulePrefs>
تتطابق نقاط نهاية عناوين URL الثلاثة في العنصر <Service>
مع نقاط نهاية رموز OAuth المميزة من Google. في ما يلي شرح لمَعلمات طلب البحث:
scope
هذه المَعلمة مطلوبة في عنوان URL للطلب. لن يتمكّن تطبيقك المصغّر من الوصول إلى البيانات إلا من
scope
المستخدَمة في هذه المَعلمة. في هذا المثال، ستتمكّن الأداة من الوصول إلى Blogger. إذا كان تطبيقك المصغّر يريد الوصول إلى أكثر من Google Data API واحد، يمكنك ربطscope
الإضافية بعلامة%20
. على سبيل المثال، إذا أردت الوصول إلى كل من "تقويم Google" وBlogger، اضبط النطاق علىhttp://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/
.oauth_callback
هذه المَعلمة اختيارية في عنوان URL الخاص بالتفويض. ستتم إعادة توجيه صفحة الموافقة على OAuth إلى عنوان URL هذا بعد أن يوافق المستخدم على الوصول إلى بياناته. يمكنك اختيار عدم تضمين هذه المَعلمة أو ضبطها على "صفحتك المعتمَدة"، أو من الأفضل استخدام
http://oauth.gmodules.com/gadgets/oauthcallback
. يوفر الخيار الثاني أفضل تجربة للمستخدمين عند تثبيت الأداة للمرة الأولى. توفّر هذه الصفحة مقتطفًا من JavaScript يغلق النافذة المنبثقة تلقائيًا.
بعد أن أصبح لدينا أداة تستخدم OAuth، على المستخدم الموافقة على الوصول إلى بياناته. في ما يلي خطوات المصادقة:
- يتم تحميل الأداة للمرة الأولى وتحاول الوصول إلى بيانات المستخدم على Blogger.
- يتعذّر تنفيذ الطلب لأنّ المستخدم لم يمنح إذن الوصول إلى الأداة. لحسن الحظ، يحتوي العنصر الذي تم عرضه في الرد على عنوان URL (
response.oauthApprovalUrl
) سنرسل المستخدم إليه لتسجيل الدخول. تعرض الأداة "تسجيل الدخول إلى Blogger" وتضبط قيمة href على قيمةoauthApprovalUrl
. - بعد ذلك، ينقر المستخدم على "تسجيل الدخول إلى Blogger"، وتُفتح صفحة الموافقة على OAuth في نافذة منفصلة. ينتظر الأداة أن ينهي المستخدم عملية الموافقة من خلال عرض رابط: "لقد وافقت على الوصول".
- في النافذة المنبثقة، سيختار المستخدم منح/رفض إذن الوصول إلى الأداة. بعد النقر على "منح الإذن بالوصول"، سيتم نقلهم إلى
http://oauth.gmodules.com/gadgets/oauthcallback
وسيتم إغلاق النافذة. - يتعرّف الأداة على النافذة المغلقة ويحاول الوصول إلى Blogger مرة ثانية من خلال إعادة طلب بيانات المستخدم. لاكتشاف إغلاق النافذة، استخدمتُ معالجًا للنوافذ المنبثقة. إذا لم تستخدم هذا الرمز، يمكن للمستخدم النقر يدويًا على "لقد وافقت على الوصول".
- تعرض الأداة الآن واجهة المستخدم العادية. سيظل هذا العرض ساريًا ما لم يتم إبطال رمز المصادقة المميز ضمن IssuedAuthSubTokens.
من الخطوات المذكورة أعلاه، تتضمّن الأدوات مفهوم ثلاث حالات مختلفة:
- لم تتم مصادقته على المستخدم بدء عملية الموافقة.
- في انتظار موافقة المستخدم على منح إذن الوصول إلى بياناته
- تمت المصادقة. تعرض الأدوات حالتها الوظيفية العادية.
في أداتي، استخدمتُ حاويات <div>
لفصل كل مرحلة:
<Content type="html"> <![CDATA[ <!-- Normal state of the gadget. The user is authenticated --> <div id="main" style="display:none"> <form id="postForm" name="postForm" onsubmit="savePost(this); return false;"> <div id="messages" style="display: none"></div> <div class="selectFeed">Publish to: <select id="postFeedUri" name="postFeedUri" disabled="disabled"><option>loading blog list...</option></select> </div> <h4 style="clear:both">Title</h4> <input type="text" id="title" name="title"/> <h4>Content</h4> <textarea id="content" name="content" style="width:100%;height:200px;"></textarea> <h4 style="float:left;">Labels (comma separated)</h4><img src="blogger.png" style="float:right"/> <input type="text" id="categories" name="categories"/> <p><input type="submit" id="submitButton" value="Save"/> <input type="checkbox" id="draft" name="draft" checked="checked"/> <label for="draft">Draft?</label></p> </form> </div> <div id="approval" style="display: none"> <a href="#" id="personalize">Sign in to Blogger</a> </div> <div id="waiting" style="display: none"> <a href="#" id="approvalLink">I've approved access</a> </di <!-- An errors section is not necessary but great to have --> <div id="errors" style="display: none"></div> <!-- Also not necessary, but great for informing users --> <div id="loading"> <h3>Loading...</h3> <p><img src="ajax-loader.gif"></p> </div> ]]> </Content>
يتم عرض كل <div>
بشكل منفصل باستخدام showOnly()
. راجِع مثال الأداة الكامل للحصول على تفاصيل حول هذه الدالة.
استخدام مكتبة برامج JavaScript للعميل
لاسترداد المحتوى البعيد في OpenSocial، عليك إجراء طلب إلى الطريقة gadgets.io.makeRequest
باستخدام واجهة برمجة التطبيقات gadgets.*
.
ومع ذلك، بما أنّنا بصدد إنشاء أداة Google Data، لا داعي لاستخدام واجهات برمجة التطبيقات gadgets.io.*
. بدلاً من ذلك، يمكنك الاستفادة من مكتبة برامج JavaScript التي تتضمّن طرقًا خاصة لتقديم الطلبات إلى كل خدمة من خدمات "بيانات Google".
ملاحظة: في وقت كتابة هذه المقالة، كانت مكتبة JavaScript متوافقة فقط مع Blogger وتقويم Google وجهات اتصال Google وGoogle Finance وGoogle Base. لاستخدام إحدى واجهات برمجة التطبيقات الأخرى، استخدِم gadgets.io.makeRequest
بدون المكتبة.
جارٍ تحميل المكتبة
لتحميل مكتبة JavaScript، أدرِج أداة التحميل الشائعة في القسم <Content>
واستورِد المكتبة بعد تهيئة الأداة. سيساعد توفير دالة ردّ الاتصال إلى gadgets.util.registerOnLoadHandler()
في تحديد الوقت الذي يصبح فيه التطبيق المصغّر جاهزًا:
<Content type="html"> <![CDATA[ ... <script src="https://www.google.com/jsapi"></script> <script type="text/javascript"> var blogger = null; // make our service object global for later // Load the JS library and try to fetch data once it's ready function initGadget() { google.load('gdata', '1.x', {packages: ['blogger']}); // Save overhead, only load the Blogger service google.setOnLoadCallback(function () { blogger = new google.gdata.blogger.BloggerService('google-BloggerGadget-v1.0'); blogger.useOAuth('google'); fetchData(); }); } gadgets.util.registerOnLoadHandler(initGadget); </script> ... ]]> </Content>
يطلب استدعاء blogger.useOAuth('google')
من المكتبة استخدام خادم وكيل OAuth (بدلاً من AuthSubJS، وهي طريقة المصادقة العادية).
أخيرًا، تحاول الأداة استرداد بيانات المستخدم على Blogger من خلال طلب fetchData()
. يتم تحديد هذه الطريقة أدناه.
جارٍ استرجاع البيانات
بعد إعداد كل شيء، كيف يمكننا GET
أو POST
البيانات إلى Blogger؟
من النماذج الشائعة في OpenSocial تحديد دالة باسم fetchData()
في أداتك. تتعامل هذه الطريقة عادةً مع المراحل المختلفة للمصادقة وتسترد البيانات باستخدام gadgets.io.makeRequest
. بما أنّنا نستخدم مكتبة برامج JavaScript، سيتم استبدال gadgets.io.makeRequest
بطلب إلى blogger.getBlogFeed()
:
function fetchData() { jQuery('#errors').hide(); var callback = function(response) { if (response.oauthApprovalUrl) { // You can set the sign in link directly: // jQuery('#personalize').get(0).href = response.oauthApprovalUrl // OR use the popup.js handler var popup = shindig.oauth.popup({ destination: response.oauthApprovalUrl, windowOptions: 'height=600,width=800', onOpen: function() { showOnly('waiting'); }, onClose: function() { showOnly('loading'); fetchData(); } }); jQuery('#personalize').get(0).onclick = popup.createOpenerOnClick(); jQuery('#approvalLink').get(0).onclick = popup.createApprovedOnClick(); showOnly('approval'); } else if (response.feed) { showResults(response); showOnly('main'); } else { jQuery('#errors').html('Something went wrong').fadeIn(); showOnly('errors'); } }; blogger.getBlogFeed('http://www.blogger.com/feeds/default/blogs', callback, callback); }
في المرة الثانية التي يتم فيها استدعاء هذه الدالة، يحتوي response.feed
على بيانات.
ملاحظة: تستخدم الدالة getBlogFeed()
الوظيفة نفسها لمعالجة الردود والتعامل مع الأخطاء.
نشر مشاركة في Blogger
الخطوة الأخيرة هي نشر إدخال جديد في مدوّنة. يوضّح الرمز البرمجي أدناه ما يحدث عندما ينقر المستخدم على الزر "حفظ".
function savePost(form) { jQuery('#messages').fadeOut(); jQuery('#submitButton').val('Publishing...').attr('disabled', 'disabled'); // trim whitespace from the input tags var input = form.categories.value; var categories = jQuery.trim(input) != '' ? input.split(',') : []; jQuery.each(categories, function(i, value) { var label = jQuery.trim(value); categories[i] = { scheme: 'http://www.blogger.com/atom/ns#', term: label }; }); // construct the blog post entry var newEntry = new google.gdata.blogger.BlogPostEntry({ title: { type: 'text', text: form.title.value }, content: { type: 'text', text: form.content.value }, categories: categories }); // publish as draft? var isDraft = form.draft.checked; if (isDraft) { newEntry.setControl({draft: {value: google.gdata.Draft.VALUE_YES}}); } // callback for insertEntry() var handleInsert = function(entryRoot) { var entry = entryRoot.entry; var str = isDraft ? '(as draft)' : '<a href="' + entry.getHtmlLink().getHref() + '" target="_blankt">View it</a>'; jQuery('#messages').html('Post published! ' + str).fadeIn(); jQuery('#submitButton').val('Save').removeAttr('disabled'); }; // error handler for insertEntry() var handleError = function(e) { var msg = e.cause ? e.cause.statusText + ': ' : ''; msg += e.message; alert('Error: ' + msg); }; blogger.insertEntry(form.postFeedUri.value, newEntry, handleInsert, handleError); }
الخاتمة
أصبح لديك الآن اللبنات الأساسية لبدء ترميز أداة تستند إلى Google Data APIs.
نأمل أن تكون هذه المقالة قد ساعدتك في فهم مدى سهولة مصادقة الأدوات باستخدام OAuth Proxy. إنّ الجمع بين هذه الأداة الفعّالة ومكتبة عميل JavaScript الخاصة ببيانات Google يسهّل إنشاء أدوات مثيرة للاهتمام وتفاعلية ومتطورة.
إذا كانت لديك أي أسئلة أو ملاحظات حول هذه المقالة، يُرجى زيارتنا في منتدى مناقشة واجهات برمجة التطبيقات لحسابات Google.
الموارد
- كتابة أدوات OAuth (مستندات الأدوات الكاملة)
- استخدام بروتوكول OAuth مع Google Data APIs (مقالة حول استخدام بروتوكول OAuth مع Google Data APIs)
- مصادقة OAuth لتطبيقات الويب (مستندات OAuth الكاملة)
- مكتبة برامج JavaScript للعميل
- منتدى مناقشة واجهات برمجة التطبيقات لحسابات Google