يمكن استخدام الدخول الموحد (Single Sign On) للتعامل مع مصادقة مستخدمين Discourse من موقع منفصل. يحتوي الموضوع Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) على تفاصيل حول كيفية تنفيذ DiscourseConnect.
المشكلة
مع DiscourseConnect، يتم إنشاء أو تحديث مستخدمين Discourse عند تسجيل دخولهم إلى Discourse من موقعك الخارجي. لكن ما لا يتعامل معه هو الحالات التي تحتاج فيها إلى إنشاء أو تحديث مستخدمين Discourse دون أن يقوموا بتسجيل الدخول إلى موقعك. بالنسبة للمواقع التي تستخدم DiscourseConnect، يجب التعامل مع هذه الحالات عن طريق إرسال طلب POST مصادق عليه إلى مسار sync_sso.
إذا كنت تستخدم مكتبة Discourse API (gem)، فيمكنك استخدام دالة
sync_ssoالخاصة بالمكتبة بدلاً من استخدام الكود التالي. راجع دليل الأمثلة للحصول على تعليمات حول كيفية استخدام الدالة.
كمثال، سنتناول حالة يتم فيها إضافة مستخدم إلى مجموعة في الموقع الرئيسي، ويحتاج إلى إضافته إلى مجموعة مقابلة في Discourse دون الحاجة إلى تسجيل الدخول أولاً باستخدام DiscourseConnect. اسم المجموعة في كل من الموقع والمنتدى هو ‘eurorack’. external_id للمستخدم هو 1 و بريده الإلكتروني هو bob@example.com. يستخدم الكود التالي لغة PHP. يمكن تطبيق الفكرة الأساسية على أي لغة برمجة.
إعداد بيانات اعتماد واجهة برمجة التطبيقات ومفتاح سر SSO
$api_key = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
$api_username = 'system';
$discourse_connect_secret = 'jdhb19*Xh3!nu(#k';
إعداد معلمات sso
لمعرفة المعلمات المتاحة، راجع قسم ACCESSORS في ملف discourse_connect_base.rb. المعلمة التي يجب تضمينها لتحديث مستخدم موجود هي external_id. إذا كنت تستدعي sync_sso لمستخدم غير موجود بعد في Discourse، فيجب عليك تضمين معلمات username و email. سيقوم Discourse باستخدام username و email لإنشاء مستخدم جديد.
لإضافة مستخدم إلى مجموعة، قم بتضمين معلمة add_groups. لإزالة مستخدم من مجموعة، قم بتضمين معلمة remove_groups. يجب أن تكون القيمة لأي من هاتين المعلمتين عبارة عن سلسلة مفصولة بفواصل من أسماء المجموعات. لا يُسمح بمسافات بين أسماء المجموعات.
يتم تضمين معلمة
require_activationفي الحمولة (payload). يجب تعيينها إلىtrueإذا لم يتم التحقق من صحة بريد المستخدم الإلكتروني في الموقع الرئيسي. مع لغةPHP، يجب تعيين المعلمة إلى السلسلة ‘true’ لتجنب تحويلها إلى الرقم1. إذا قمت بالتحقق من صحة عنوان البريد الإلكتروني للمستخدم، فلا تحتاج إلى تضمين هذه المعلمة.
// إنشاء مصفوفة من معلمات SSO.
$sso_params = array(
'external_id' => 1,
'email' => 'bob@example.com',
'username' => 'bob',
'add_groups' => 'eurorack',
'require_activation' => 'true',
);
// تحويل معلمات SSO إلى حمولة SSO وتوليد توقيع SSO.
$sso_payload = base64_encode( http_build_query( $sso_params ) );
$sig = hash_hmac( 'sha256', $sso_payload, $discourse_connect_secret );
إرسال طلب POST
في هذا المثال سأستخدم curl، وأضبط user_agent على ‘WordPress/4.9.4’، وعنوان URL للمنتدى على https://forum.example.com
$url = 'https://forum.example.com/admin/users/sync_sso';
$post_fields = array(
'sso' => $sso_payload,
'sig' => $sig,
);
$headers = array("Content-Type: multipart/form-data;","Api-Key: $api_key","Api-Username: $api_username",);
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $post_fields ) );
curl_setopt( $ch, CURLOPT_USERAGENT, 'WordPress/4.9.4' );
$result = curl_exec( $ch );
if ( curl_errno( $ch ) !== 0 ) {
// التعامل مع الخطأ، استدعاء curl_close( $ch ) والعودة.
}
curl_close( $ch );
$discourse_user = json_decode( $result );
تحديث المستخدمين الموجودين
ستقوم الطلبات المرسلة إلى مسار sync_sso بتحديث خصائص المستخدمين الموجودين بنفس الطريقة التي تحدث بها إذا قام المستخدم بتسجيل الدخول إلى الموقع باستخدام DiscourseConnect. وهذا يعني أن قيم إعدادات الموقع auth overrides و discourse connect overrides في موقعك سيتم احترامها لهذه الطلبات. على سبيل المثال، لتحديث عنوان البريد الإلكتروني للمستخدمين الحاليين باستخدام طلبات sync_sso، يجب تفعيل إعداد auth overrides email. إليك الإعدادات ذات الصلة:
auth overrides emailauth overrides usernameauth overrides namediscourse connect overrides avatardiscourse connect overrides biodiscourse connect overrides groupsdiscourse connect overrides profile backgrounddiscourse connect overrides card backgrounddiscourse connect overrides locationdiscourse connect overrides website
قراءات إضافية
لمعرفة ما يحدث، راجع كود sync_sso، ودالة DiscourseConnectBase parse، ودالة DiscourseConnect lookup_or_create_user.
هناك أيضًا نسخة JavaScript من هذا الدليل لأولئك الذين يستخدمون Node.js.