it-swarm.com.ru

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;
12
Éric Senterre

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

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

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

22
M.Dalda

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

9
Ruhul Amin

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

9
che-azeh

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

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

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

$helper = $fb->getRedirectLoginHelper();  
3
ashutosh

Это общая проблема, с которой многие сталкиваются в 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();
} ?>
2
Er Prabhjot Singh Tugger

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

У меня была та же проблема, что и у О.П., и это исправило мою проблему.

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

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

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

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

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

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

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

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

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

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

1
Rajender Joshi

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

Я решил проблему, добавив параметр persistent_data_handler в мой экземпляр приложения на Facebook с помощью специального обработчика, который реализует интерфейс PersistentDataInterface Facebook 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);
    }
}
1
Julien F.

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

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

1
Nanang Koesharwanto

Для меня проблема решена, просто начав сессию, добавив:

session_start();

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

Я также должен был добавить это:

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

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

1
Adam Tong

Как я ответил здесь: Facebook SDK возвратил ошибку: сбой при проверке подделки межсайтовых запросов. Параметр "state" из URL и сеанса не совпадают

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

1
Chao Chen

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

Чтобы решить эту проблему, я сохраняю эту переменную "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 часов работы :) Пока, Алекс.

0
ale500

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

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

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

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

0
Éric Senterre

Если session_start () по-прежнему не решает проблему, вы добавили неверный URI в действительный OAuth URI перенаправления вашего приложения для разработчиков Facebook.

Для решения: во-первых, зайдите в ваш fb-callback.php, найдите URI, который вы поместили в функцию заголовка, например: header ("Location: https: //localhost/home.php "). Затем перейдите в приложения для разработчиков Facebook, затем на боковой панели нажмите "Вход в Facebook", который находится на вкладке "Продукты", затем нажмите "Настройки". В действительные URI перенаправления OAuth добавьте URI, указанный в заголовке. Из моего примера я поставлю https: //localhost/home.php .

Надеюсь это поможет.

0
John Joshua Villegas

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

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

0
Tharindu

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

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();
0
Emastmagy MastMagy

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

0
Jonas Menk

Для меня это произошло из-за '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'
  ]);
0
Amit Tyagi

Для меня решение было поймать исключение, заменив пространство имен 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;
}
0
michalzuber