إذا شاهد موقعنا على الويب أن Facebook موقّع في المستخدم لديه معرف المستخدم 678678678 في ملف تعريف الارتباط ، فكيف نعرف أن ملف تعريف الارتباط هذا ليس مزيفًا؟

StackOverflow https://stackoverflow.com/questions/4002616

  •  25-09-2019
  •  | 
  •  

سؤال

أعتقد أنه إذا أجرينا مكالمات على Facebook باستخدام REST أو GRATH API ، فسوف نعرف ما إذا كان ذلك مزيفًا لأنه سيعود قائلاً جلسة مزيفة / Auth_token / Access_Token. ولكن ماذا لو نعرض معلومات DB الخاصة بنا ، مثل "قائمة المنتجات الأكثر تفضيلاً" للمستخدم ، فإننا لا نقوم بأي مكالمة إلى Facebook ولكن نعرض بيانات DB الخاصة بنا. كيف نعرف أنه هو المستخدم حقًا ، وليس شخص ما يزيح ملف تعريف الارتباط؟

هل كانت مفيدة؟

المحلول

عندما تقرأ ملف تعريف الارتباط مع Facebook ، فإنه يحتوي على قيمة تسمى "SIG". مع هذه القيمة ، وقيم ملفات تعريف الارتباط الأخرى ، وسرية التطبيق الخاصة بك ، يمكنك تجزئة محتويات ملف تعريف الارتباط والتحقق منها ضد SIG. إذا تطابق ، فإن ملف تعريف الارتباط صالح. يمكنك الوثوق بهذه النتيجة لأنك فقط أنت و Facebook يمكنهم الوصول إلى Secret App. فيما يلي مثال على كيفية قيام PHP SDK من Facebook. أي Facebook SDK محترم سيفعل كل هذا من أجلك داخليًا.

/**
   * Validates a session_version=3 style session object.
   *
   * @param Array $session the session object
   * @return Array the session object if it validates, null otherwise
   */
  protected function validateSessionObject($session) {
    // make sure some essential fields exist
    if (is_array($session) &&
        isset($session['uid']) &&
        isset($session['access_token']) &&
        isset($session['sig'])) {
      // validate the signature
      $session_without_sig = $session;
      unset($session_without_sig['sig']);
      $expected_sig = self::generateSignature(
        $session_without_sig,
        $this->getApiSecret()
      );
      if ($session['sig'] != $expected_sig) {
        self::errorLog('Got invalid session signature in cookie.');
        $session = null;
      }
      // check expiry time
    } else {
      $session = null;
    }
    return $session;
  }

هنا هو نفس الشيء في C# (Facebook C# SDK):

 /// <summary>
    /// Validates a session_version=3 style session object.
    /// </summary>
    /// <param name="session">The session to validate.</param>
    protected override void ValidateSessionObject(FacebookSession session)
    {
        if (session == null)
        {
            return;
        }

        var signature = this.GenerateSignature(session);
        if (session.Signature == signature.ToString())
        {
            return;
        }

        session = null;
    }

    /// <summary>
    /// Generates a MD5 signature for the facebook session.
    /// </summary>
    /// <param name="session">The session to generate a signature.</param>
    /// <returns>An MD5 signature.</returns>
    /// <exception cref="System.ArgumentNullException">If the session is null.</exception>
    /// <exception cref="System.InvalidOperationException">If there is a problem generating the hash.</exception>
    protected override string GenerateSignature(FacebookSession session)
    {
        var args = session.Dictionary;
        StringBuilder payload = new StringBuilder();
        var parts = (from a in args
                     orderby a.Key
                     where a.Key != "sig"
                     select string.Format(CultureInfo.InvariantCulture, "{0}={1}", a.Key, a.Value)).ToList();
        parts.ForEach((s) => { payload.Append(s); });
        payload.Append(this.ApiSecret);
        byte[] hash = null;
        using (var md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create())
        {
            if (md5 != null)
            {
                hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload.ToString()));
            }
        }

        if (hash == null)
        {
            throw new InvalidOperationException("Hash is not valid.");
        }

        StringBuilder signature = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            signature.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
        }

        return signature.ToString();
    }

نصائح أخرى

الشيء الوحيد الذي يمكنك الوثوق به هو session_key ل API القديم الراحة و access_token لـ Graph API. بمجرد أن تحصل عليه ، قم بتمريره إلى جانب الخادم مع طلب RetriRval لبياناتك. على جانب الخادم ، اتصل على واجهة برمجة تطبيقات Facebook واحصل على userId الحالي. بمجرد حصولك على userId ، يمكنك تخزينه في جلسة واستخدامها لاحقًا.

لا تخزنها في ملف تعريف الارتباط. ضعها في متغير جلسة ، وبهذه الطريقة يمكنك السيطرة عليها

لا تضع معرف المستخدم في ملف تعريف الارتباط. يجب أن يكون ملف تعريف الارتباط للجلسة مجرد رقم عشوائي يقوم بتخطيط سجل في قاعدة بيانات الجلسة من جانب الخادم. يتم تخزين أي بيانات مرتبطة بتلك الجلسة فقط من جانب الخادم.

وبهذه الطريقة ، من أجل تزوير جلسة ، يتعين على المهاجم تخمين رقم عشوائي قيد الاستخدام بالفعل في ذلك الوقت. بالنظر إلى أن هناك الكثير من الأرقام العشوائية وجلسات الجلسات ، فهذا مستحيل تقريبًا.

هناك بعض الأساليب هنا.

غير فعال: كلما قمت بإجراء عملية مصادقة ، احصل على ملف تعريف الارتباط FB واستخدم البيانات الموجودة فيه لإجراء مكالمة API وهمية لترى أن رمز الوصول صالح ويطابق المستخدم (أي Grab /Me؟ fields = id).

أكثر كفاءة: في المرة الأولى التي ترى فيها ملف تعريف ارتباط FB للمستخدم ، قم بتخزين ملف تعريف الارتباط في جلسة من جانب الخادم للمستخدم (مع معرف جلسة إلى حد ما إلى حد ما إلى العميل في ملف تعريف الارتباط).

نهج آخر ، ولا يتطلب حالة جلسة من جانب الخادم: في المرة الأولى التي ترى فيها ملف تعريف ارتباط FB للمستخدم ، HMAC ملف تعريف الارتباط باستخدام سر فقط خوادمك ، وتخزين التجزئة الناتجة في ملف تعريف الارتباط. ثم يمكنك التحقق مما إذا كان هناك تجزئة صالحة لملف تعريف الارتباط FB ، وإذا كان الأمر كذلك ، فأنت تثق به. خلاف ذلك ، تعود إلى التحقق من الصحة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top