Wenn auf unserer Website das in Benutzer signierte Facebook im Cookie die Benutzer -ID 678678678 hat, woher wissen wir, dass dieses Cookie nicht gefälscht ist?

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

  •  25-09-2019
  •  | 
  •  

Frage

Ich denke, wenn wir mit REST- oder Graph -API Anrufe auf Facebook tätigen, werden wir wissen, ob es falsch ist, weil es zurückkommt, wenn sie eine gefälschte Sitzung / auth_token / access_token erzielen. Aber was ist, wenn wir unsere eigenen DB -Informationen wie die "am meisten bevorzugte Produktliste" des Benutzers anzeigen? Woher wissen wir, dass es wirklich der Benutzer ist, nicht jemand, der den Cookie vornimmt?

War es hilfreich?

Lösung

Wenn Sie ein Cookie mit Facebook lesen, enthält es einen Wert namens "Sig". Mit diesem Wert, den anderen Cookie -Werten und Ihrem App geheimen Sie den Inhalt des Cookies und validieren sie gegen die Sig. Wenn sie übereinstimmen, ist das Cookie gültig. Sie können diesem Ergebnis vertrauen, da nur Sie und Facebook Zugriff auf das App -Geheimnis haben. Hier ist das Beispiel, wie Facebooks PHP SDK es tut. Jeder respektable Facebook -SDK wird dies alles intern für Sie tun.

/**
   * 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;
  }

Hier ist das gleiche in 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();
    }

Andere Tipps

Das einzige, was Sie vertrauen können, ist session_key für alte REST -API und access_token Für Graph -API. Sobald Sie es bekommen haben, geben Sie es mit Ihrer Daten -Retrirval -Anfrage an eine Serverseite weiter. Rufen Sie auf der Server -Seite die Facebook -API auf und erhalten Sie aktuelle BenutzerID. Sobald Sie UserID haben, können Sie es in einer Sitzung speichern und später verwenden.

Bewahren Sie es nicht in einem Keks auf. Setzen Sie es in eine Sitzungsvariable ein, auf diese Weise haben Sie die Kontrolle

Geben Sie keine Benutzer -ID in ein Cookie ein. Das Sitzungs-Cookie sollte nur eine zufällige Nummer sein, die in Ihrer serverseitigen Sitzungsdatenbank auf einen Datensatz zugeordnet ist. Alle dieser Sitzung zugeordneten Daten werden nur serverseitig gespeichert.

Um eine Sitzung zu fälschen, müsste ein Angreifer eine zufällige Zahl erraten, die zu diesem Zeitpunkt tatsächlich verwendet wird. Angesichts der Tatsache, dass es viele zufällige Zahlen gibt und Sitzungen verfallen, ist das fast unmöglich.

Hier gibt es einige Ansätze.

Ineffizient: Wenn Sie einen authentifizierten Operation ausführen, schnappen Sie sich das FB -Cookie und verwenden Sie die darin enthaltenen Daten, um einen Dummy -API -Anruf aufzunehmen, um festzustellen, dass das Zugriffs -Token gültig ist und dem Benutzer übereinstimmt (dh Grab /Me? Fields = ID).

Effizienter: Wenn Sie zum ersten Mal einen FB-Cookie für einen Benutzer sehen, speichern Sie das Cookie in einer serverseitigen Sitzung für den Benutzer (mit einer ausreichend harte Session-ID in einem Cookie).

Ein anderer Ansatz und nicht serverseitigem Sitzungsstatus erforderlich: Wenn Sie zum ersten Mal einen FB-Cookie für einen Benutzer sehen, HMAC, das Cookie verwendet nur ein Geheimnis, das nur Ihre Server haben, und speichern Sie diesen resultierenden Hash in einem Cookie. Dann können Sie überprüfen, ob es einen gültigen Hash des FB -Cookies gibt, und wenn ja, vertrauen Sie ihm. Andernfalls greifen Sie auf die Validierung zurück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top