Подтвердить что ты не робот

Facebook PHP SDK 5:: API 2.4:: Ошибка проверки подделки на основе межсайтового запроса. Обязательное состояние "состояние" отсутствует

Я сделал очень простой PHP script, просто чтобы попытаться войти через Facebook и получить accessToken. Но когда я пытаюсь использовать следующий код, я получаю исключение из SDK: "Ошибка проверки подделки на основе межсайтового запроса не удалась. Обязательное состояние" состояние "отсутствует.".

Вот мой код:

require_once __DIR__ . '/facebook-sdk-v5/autoload.php';
session_start();

$fb = new Facebook\Facebook([
    'app_id' => '{my-own-app-id}',
    'app_secret' => '{my-own-app-secret}'
]);

// Check to see if we already have an accessToken ?
if (isset($_SESSION['facebook_access_token'] )) {
    $accessToken = $_SESSION['facebook_access_token'];
    echo "Horray we have our accessToken:$accessToken<br />\n";

} else {
    // We don't have the accessToken
    // But are we in the process of getting it ? 
    if (isset($_REQUEST['code'])) {
        $helper = $fb->getRedirectLoginHelper();
        try {
            $accessToken = $helper->getAccessToken();
            } catch(Facebook\Exceptions\FacebookResponseException $e) {
              // When Graph returns an error
              echo 'Graph returned an error: ' . $e->getMessage();
              exit;
        } catch(Facebook\Exceptions\FacebookSDKException $e) {
              // When validation fails or other local issues
              echo 'Facebook SDK returned an error: ' . $e->getMessage();
            exit;
        }

        if (isset($accessToken)) {
              // Logged in!
              $_SESSION['facebook_access_token'] = (string) $accessToken;

              // Now you can redirect to another page and use the
              // access token from $_SESSION['facebook_access_token']

              echo "Finally logged in! Token:$accessToken";
        }           
    } else {
        // Well looks like we are a fresh dude, login to Facebook!
        $helper = $fb->getRedirectLoginHelper();
        $permissions = ['email', 'user_likes']; // optional
        $loginUrl = $helper->getLoginUrl('http://mywebsite.com/myapp/index.php', $permissions);

        echo '<a href="' . $loginUrl . '">Log in with Facebook!</a>';
    }

}

exit;
4b9b3361

Ответ 1

Мне пришлось добавлять эти строки на некоторые серверы:

$helper = $fb->getRedirectLoginHelper();
if (isset($_GET['state'])) {
    $helper->getPersistentDataHandler()->set('state', $_GET['state']);
}

Я получаю эту ошибку случайным образом, в зависимости от конфигурации сервера.

Ответ 2

Если вы используете "www" версию своего сайта для создания ссылки для входа в систему, и вы перенаправляетесь на версию, отличную от www, вы столкнетесь с проблемами со своей сессией. Поэтому убедитесь, что вы открыли www-версию своего сайта, а затем определили URL-адрес обратного вызова в той же версии www. Кроме того, вы можете определить постоянные переадресации в конфигурации вашего сервера, чтобы убедиться, что любой пользователь, обращающийся к вашему сайту с версии, отличной от www, перенаправляется на версию www или наоборот.

Ответ 4

вы получаете эту ошибку, если имя хоста происхождения отличается от имени целевого узла после аутентификации.

$loginUrl = $helper->getLoginUrl('http://mywebsite.com/myapp/index.php', $permissions);

с этим утверждением, если посетитель на вашем веб-сайте использовал http://www.mywebsite.com/, будет увеличена ошибка межсайтового сайта.

Вы должны убедиться, что имя источника и целевое имя хоста точно совпадают, включая конечный префикс www.

Фиксированная версия:

$loginUrl = $helper->getLoginUrl('http://'.$_SERVER['SERVER_NAME'].'/myapp/index.php', $permissions);

Ответ 5

Я также столкнулся с той же проблемой и после исследования stackoverflow установка линии

$_SESSION['FBRLH_state']=$_GET['state']; 

выше решила мою проблему

$helper = $fb->getRedirectLoginHelper();  

Ответ 6

Установка [PersistentDataHandler] явно до получения ваших токенов гарантирует, что запрос будет успешным. Ниже показано, как получить $_GET ['state'] и просто ввести его в "для использования [помощник]" на Symfony 2.x | 3.х

У меня была такая же проблема, как у O.P. и эта проблема была исправлена.

//create your new facebook sdk instance
$this->fb = new Facebook([
   'app_id' => $facebookAppId,
   'app_secret' =>$facebookAppSecret,
   'default_graph_version' =>$facebookDefaultGraphVersion
]);    

//retrieve the helper
$this->helper = $this->fb->getRedirectLoginHelper();

//below is the money shot
//setting this explicitly before you get your tokens will guarantee that the request will be a success. It Fetches $_GET['state'] & simply injects it into the "to be used [helper]"
$this->helper->getPersistentDataHandler()->set('state', $request->query->get('state'));

Ответ 7

Для меня проблема решена теперь, только запустив сеанс, добавив следующее:

session_start();

в начале обоих файлов (первый файл, генерирующий URL-адрес facebook и файл обратного вызова: login.php и fb-callback.php(https://developers.facebook.com/docs/php/howto/example_facebook_login)).

Мне также пришлось добавить это:

$config['app_id'] = 'myapp_id';

вверху, чтобы предотвратить другую не связанную ошибку.

Ответ 9

Laravel 5.2

У меня тоже есть эта ошибка. Ошибка проверки подделки на основе межсайтового запроса. Обязательное состояние параметра "отсутствует".

и после чтения this в течение нескольких часов. Я попытался изменить поставщика script.

в vendor\facebook\php-sdk-v4\src\Facebook\Helpers\FacebookRedirectLoginHelper.php в строке 123 меняет этот script:

private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
{
    $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
    $this->persistentDataHandler->set('state', $state);

    return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
}

в (я добавляю Session::put('state', $state);)

private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&')
{
    $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH);
    $this->persistentDataHandler->set('state', $state);
    Session::put('state', $state);
    return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator);
}

и в строке 234, я изменяю этот script:

protected function validateCsrf()
{
    $state = $this->getState();
    $savedState = $this->persistentDataHandler->get('state');

    if (!$state || !$savedState) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
    }

    $savedLen = strlen($savedState);
    $givenLen = strlen($state);

    if ($savedLen !== $givenLen) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

    $result = 0;
    for ($i = 0; $i < $savedLen; $i++) {
        $result |= ord($state[$i]) ^ ord($savedState[$i]);
    }

    if ($result !== 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }
}

в (я добавил $this->persistentDataHandler->set('state', Session::get('state'));)

protected function validateCsrf()
{
    $state = $this->getState();
    $this->persistentDataHandler->set('state', Session::get('state'));
    $savedState = $this->persistentDataHandler->get('state');

    if (!$state || !$savedState) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.');
    }

    $savedLen = strlen($savedState);
    $givenLen = strlen($state);

    if ($savedLen !== $givenLen) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }

    $result = 0;
    for ($i = 0; $i < $savedLen; $i++) {
        $result |= ord($state[$i]) ^ ord($savedState[$i]);
    }

    if ($result !== 0) {
        throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.');
    }
}

Это все, что я сделал. и ошибка исчезла.

Ответ 10

Я столкнулся с подобной проблемой и нашел решение Nanang Koesharwanto. Это больше похоже на quirk, поскольку изменение исходных файлов в каталоге поставщиков - очень плохая идея. Так вот трюк.

public function callback(Request $request)
{
    $this->helper->getPersistentDataHandler()->set('state', $request->state);
    return $this->helper->getAccessToken();
}

Если это не удается, введите use Session; в ваш контроллер.

Ответ 11

Это обычная проблема, с которой сталкиваются многие люди в FB Api. это только проблема СЕССИИ. Чтобы решить эту проблему, добавьте некоторый код.

При обратном вызове script обычно fb-callback.php добавляет "session_start();" перед тем, как вы включите файл автозагрузки facebook. а затем "$ _SESSION ['FBRLH_state'] = $_ GET ['state'];" после "$ helper = $fb- > getRedirectLoginHelper();" линия.

Пример:

<?php 
session_start(); /*Add session start*/
include 'vendor/autoload.php';
include 'config.php'; /*Facebook Config*/
$helper = $fb->getRedirectLoginHelper();
$_SESSION['FBRLH_state']=$_GET['state']; /*Add This*/
try {
  $accessToken = $helper->getAccessToken();
} ?>

Ответ 12

Реальная проблема здесь заключалась в кодировании моего PHP файла. Я использовал UTF8, но это должен был быть UTF8 без спецификации.

Побочным эффектом неправильной кодировки было то, что моя сессия не работала должным образом, а затем SDK не смог получить необходимую информацию для правильной работы.

Правильно настроенная отчетность об ошибках сообщила бы, что проблема была прямолинейной.

Я думаю, что мы можем заполнить эту ошибку в категории "noob". Но все же, я думаю, что это может быть полезно для других нубов, подобных мне.

Ответ 13

Наконец, просмотрев код FB, я обнаружил, что проблема "Проверка подделки на основе межсайтового запроса не удалась. Требуемое состояние параметра" отсутствует "и аналогичные данные вызваны переменной PHP $_SESSION ['FBRLH_state'], которая для некоторых" странных "Причина, когда FB вызывает файл обратного вызова login.

Чтобы решить эту проблему, я сохраняю эту переменную "FBRLH_state" ПОСЛЕ вызова функции $helper- > getLoginUrl (...). Очень важно делать это только после вызова этой функции из-за того, что внутри этой функции находится переменная $_SESSION ['FBRLH_state'].

Ниже пример моего кода в login.php:

$uri=$helper->getLoginUrl($uri, $permissions);
foreach ($_SESSION as $k=>$v) {                    
    if(strpos($k, "FBRLH_")!==FALSE) {
        if(!setcookie($k, $v)) {
            //what??
        } else {
            $_COOKIE[$k]=$v;
        }
    }
}
var_dump($_COOKIE);

И в login-callback.php перед вызовом всего кода FB:

foreach ($_COOKIE as $k=>$v) {
    if(strpos($k, "FBRLH_")!==FALSE) {
        $_SESSION[$k]=$v;
    }
}

И последнее, но не менее важное, помните также, чтобы включить код для сеанса PHP, поэтому..

if(!session_id()) {
    session_start();
}
...
...
...
...
<?php session_write_close() ?>

Я надеюсь, что этот ответ поможет вам сэкономить 8-10 часов работы:) Пока, Алекс.

Ответ 14

вы должны убедиться, что запуск сеанса перед запуском script. но опять же он выкинет 443: Network is unreachable, если вы снова начнете сеанс с того же script. надеюсь, это поможет кому-то.

Я просто использовал if (session_status() == PHP_SESSION_NONE){ session_start(); }

Ответ 15

Те из вас, кто используют cakephp 3.x и имеют эту проблему, и вы не знаете, как его решить. Добавить session_start(); в начале вашего метода auth и callback.

public function Facebookauth()
{
session_start();
 $fb = new Facebook([
      'app_id' => '{app_id}',
      'app_secret' => '{app_secret}',
      'default_graph_version' => 'v2.6',
     ..........

    ]);

you can still use 
     $session = $this->request->session();

Ответ 16

Для меня это произошло из-за 'persistent_data_handler'. Добавив это в конфигурацию Facebook, я смог заставить его работать.

session_start();
$fb = new Facebook\Facebook([
  'app_id'     => '6XXXXXXXXX',
  'app_secret' => '5XXXXXXXXXXXXXX',
  'default_graph_version' => 'v2.6', 
  'persistent_data_handler' => 'session'
  ]);

Ответ 17

Исправление для меня заключалось в изменении 'secure' => true на false в config/session.php. Я случайно установил это в true, не используя https в первую очередь.

Ответ 18

Для меня решение поймало исключение, заменив namespaced Facebook\Exceptions\FacebookSDKException на просто Exception, потому что script уже использовал его.

use Facebook\Facebook;

// code ...

$fb = new Facebook([
    'app_id' => FB_APP_ID,
    'app_secret' => FB_APP_SECRET,
    'default_graph_version' => 'v2.5',
]);

$helper = $fb->getRedirectLoginHelper();
try {
    $accessToken = $helper->getAccessToken();
} catch (Exception $e) {
    echo $e->getMessage();
    exit;
}

Ответ 19

Я пытался внедрить вход в Facebook в Symfony с помощью PHP PHP SDK, и у меня была такая же ошибка. Ошибка проверки подделки на основе межсайтового запроса. Обязательное состояние параметра "отсутствует".

Я решил проблему, добавив параметр persistent_data_handler в мою инсталляцию приложения facebook с помощью специального обработчика, который реализует PersistentDataInterface PHP PHP SDK.

Работает как шарм.

public function facebookCallbackAction(Request $request) {
    $session = $request->getSession();

    $fb = new \Facebook\Facebook([
        'app_id' => $this->container->getParameter('facebook_app_id'),
        'app_secret' => $this->container->getParameter('facebook_app_secret'),
        'default_graph_version' => 'v2.5',
        'persistent_data_handler' => new SymfonyPersistentDataHandler($session),
    ]);
}

Мой пользовательский обработчик:

use Facebook\PersistentData\PersistentDataInterface;
use Symfony\Component\HttpFoundation\Session\Session;

class SymfonyPersistentDataHandler implements PersistentDataInterface {
    protected $session;
    protected $sessionPrefix = 'FBRLH_';

    public function __construct(Session $session) {
        $this->session = $session;
    }

    public function get($key) {
        return $this->session->get($this->sessionPrefix . $key);
    }

    public function set($key, $value) {
        $this->session->set($this->sessionPrefix . $key, $value);
    }
}

Ответ 20

Наконец после всех этих приятных ошибок, я исправил все свои проблемы с другим решением, пример из документов разработчика facebook устарел.

SDK V5 и APi 2.4 работает , как в этом tutorial, описанном, необходимо определить маркер доступа

Обязательно заполните APP-IP | APP-SECRET своими учетными данными.

Пример из учебника:

$fb = new Facebook\Facebook([
      'app_id' => 'APP-ID',
      'app_secret' => 'APP-SECRET',
      'default_graph_version' => 'v2.4',
      'default_access_token' => 'APP-ID|APP-SECRET'
]);

Используйте это, а не пример в документах разработчика facebook.

Удачи:)

Ответ 21

Что бы вы ни делали. Просто не называйте getAccessToken() более одного раза. Он удаляет состояние из сеанса, как только он вызывается.