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

Я сделал очень простой PHP-скрипт, просто чтобы попытаться войти через 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; 

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

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

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

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

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

session_start () в начале обоих скриптов. Я получил решение отсюда: https://github.com/facebook/facebook-php-sdk-v4/issues/473

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

 $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); 

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

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

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

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

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

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

 $helper = $fb->getRedirectLoginHelper(); 

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

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

 //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')); 

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

 session_start(); 

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

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

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

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

Как я ответил здесь: Facebook SDK вернул ошибку: проверка подделки на основе перекрестного запроса не удалась. Параметр «состояние» из URL-адреса и сеанса не соответствует

вам необходимо убедиться, что ваша собственная функция сеанса PHP правильно установлена.

Laravel 5.2

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

и после прочтения этого часами. Я попытался изменить сценарий поставщика.

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

 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 я изменяю этот скрипт:

 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.'); } } 

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

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

В сценарии обратного вызова обычно 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(); } ?> 

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

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

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

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

Наконец, изучая 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 часов работы. Пока, Алекс.

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

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

Тем из вас, кто использует 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(); 

Для меня это происходило из-за «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' ]); 

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

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

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

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

Я решил проблему, добавив параметр persistent_data_handler к моему instanciation приложения 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); } } 

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

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

Обязательно заполните 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.

Повеселись 🙂

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