Если наш веб-сайт видит, что у пользователя Facebook, вошедшего в систему, есть идентификатор пользователя 678678678 в файле cookie, как мы узнаем, что этот файл cookie не подделан?

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

  •  25-09-2019
  •  | 
  •  

Вопрос

Я думаю, что если мы сделаем вызовы Facebook с помощью REST или Graph API, мы узнаем, подделка ли это, потому что он вернется со словами поддельный сеанс / auth_token / access_token.Но что, если мы показываем нашу собственную информацию из базы данных, такую как "список наиболее предпочитаемых продуктов пользователя", тогда мы не совершаем никаких звонков Facebook, а показываем данные нашей базы данных.Откуда мы знаем, что это действительно пользователь, а не кто-то, подделывающий файл cookie?

Это было полезно?

Решение

Когда вы читаете файл cookie с facebook, он содержит значение под названием "sig".Используя это значение, другие значения cookie и секрет вашего приложения, вы хэшируете содержимое cookie и проверяете его на соответствие sig.Если они совпадают, значит, файл cookie действителен.Вы можете доверять этому результату, потому что только вы и Facebook имеете доступ к секрету приложения.Вот пример того, как 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 для старого REST api и access_token для Graph API.Как только вы получите его, передайте его на сторону сервера с запросом на повторный анализ данных.На стороне сервера вызовите facebook api и получите текущий идентификатор пользователя.Получив идентификатор пользователя, вы можете сохранить его в сеансе и использовать позже.

не храните его в печенье.Поместите это в переменную сеанса, таким образом, у вас будет контроль

Не помещайте идентификатор пользователя в файл cookie.Файл cookie сеанса должен быть просто случайным числом, которое сопоставляется записи в вашей серверной базе данных сеансов.Любые данные, связанные с этим сеансом, хранятся только на стороне сервера.

Таким образом, чтобы подделать сеанс, злоумышленнику пришлось бы угадать случайное число, которое действительно использовалось в данный момент.Учитывая, что существует много случайных чисел и срок действия сеансов истекает, это практически невозможно.

Здесь есть несколько подходов.

Неэффективный:Всякий раз, когда вы выполняете операцию аутентификации, возьмите файл cookie FB и используйте содержащиеся в нем данные для выполнения фиктивного вызова API, чтобы убедиться, что токен доступа действителен и соответствует пользователю (т. е.захватить /меня?поля=идентификатор).

Более эффективный:Когда вы в первый раз увидите файл cookie FB для пользователя, сохраните этот файл cookie в сеансе на стороне сервера для пользователя (с достаточно трудноопределимым идентификатором сеанса, передаваемым клиенту в файле cookie).

Другой подход, и не требует состояния сеанса на стороне сервера:Когда вы в первый раз увидите файл cookie FB для пользователя, сохраните файл cookie, используя секрет, который есть только у ваших серверов, и сохраните полученный хэш в файле cookie.Затем вы можете проверить, существует ли действительный хэш файла cookie FB, и если да, то вы ему доверяете.В противном случае вы вернетесь к проверке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top