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;
Ответы
Ответ 1
Мне пришлось добавлять эти строки на некоторые серверы:
$helper = $fb->getRedirectLoginHelper();
if (isset($_GET['state'])) {
$helper->getPersistentDataHandler()->set('state', $_GET['state']);
}
Я получаю эту ошибку случайным образом, в зависимости от конфигурации сервера.
Ответ 2
Если вы используете "www" версию своего сайта для создания ссылки для входа в систему, и вы перенаправляетесь на версию, отличную от www, вы столкнетесь с проблемами со своей сессией. Поэтому убедитесь, что вы открыли www-версию своего сайта, а затем определили URL-адрес обратного вызова в той же версии www. Кроме того, вы можете определить постоянные переадресации в конфигурации вашего сервера, чтобы убедиться, что любой пользователь, обращающийся к вашему сайту с версии, отличной от www, перенаправляется на версию www или наоборот.
Ответ 3
session_start() в начале обоих скриптов. Я получил решение отсюда: https://github.com/facebook/facebook-php-sdk-v4/issues/473
Ответ 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';
вверху, чтобы предотвратить другую не связанную ошибку.
Ответ 8
Как я ответил здесь: Facebook SDK вернул ошибку: проверка подделки на основе межсайтового запроса не удалась. "Состояние" Параметр из URL-адреса и сеанса не соответствует
вам нужно убедиться, что ваша собственная функция сеанса PHP правильно установлена.
Ответ 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() более одного раза. Он удаляет состояние из сеанса, как только он вызывается.