UFO ET IT

Facebook SDK에서 오류를 반환했습니다. 교차 사이트 요청 위조 유효성 검사에 실패했습니다.

ufoet 2020. 12. 13. 10:01
반응형

Facebook SDK에서 오류를 반환했습니다. 교차 사이트 요청 위조 유효성 검사에 실패했습니다. URL 및 세션의 "상태"매개 변수가 일치하지 않습니다.


나는 이와 같은 PHP SDK를 사용하여 Facebook 사용자 ID를 얻으려고합니다.

$fb = new Facebook\Facebook([
    'app_id' => '11111111111',
    'app_secret' => '1111222211111112222',
    'default_graph_version' => 'v2.4',
]);

$helper = $fb->getRedirectLoginHelper();


$permissions = ['public_profile','email']; // Optional permissions
$loginUrl = $helper->getLoginUrl('http://MyWebSite', $permissions);

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


    try {
        $accessToken = $helper->getAccessToken();
        var_dump($accessToken);
    } 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)) {
        if ($helper->getError()) {
            header('HTTP/1.0 401 Unauthorized');
            echo "Error: " . $helper->getError() . "\n";
            echo "Error Code: " . $helper->getErrorCode() . "\n";
            echo "Error Reason: " . $helper->getErrorReason() . "\n";
            echo "Error Description: " . $helper->getErrorDescription() . "\n";
        } else {
            header('HTTP/1.0 400 Bad Request');
            echo 'Bad request';
        }
        exit;
    }

// Logged in
    echo '<h3>Access Token</h3>';
    var_dump($accessToken->getValue());

// The OAuth 2.0 client handler helps us manage access tokens
    $oAuth2Client = $fb->getOAuth2Client();

// Get the access token metadata from /debug_token
    $tokenMetadata = $oAuth2Client->debugToken($accessToken);
    echo '<h3>Metadata</h3>';
    var_dump($tokenMetadata);

// Validation (these will throw FacebookSDKException's when they fail)
    $tokenMetadata->validateAppId($config['11111111111']);
// If you know the user ID this access token belongs to, you can validate it here
//$tokenMetadata->validateUserId('123');
    $tokenMetadata->validateExpiration();

    if (!$accessToken->isLongLived()) {
        // Exchanges a short-lived access token for a long-lived one
        try {
            $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
        } catch (Facebook\Exceptions\FacebookSDKException $e) {
            echo "<p>Error getting long-lived access token: " . $helper->getMessage() . "</p>\n\n";
            exit;
        }

        echo '<h3>Long-lived</h3>';
        var_dump($accessToken->getValue());
    }

    $_SESSION['fb_access_token'] = (string)$accessToken;

하지만이 오류가 발생합니다.

Facebook SDK returned an error: 
Cross-site request forgery validation failed. 
The "state" param from the URL and session do not match.

내가 PHP에서 처음이고 Facebook sdk의 도움을 미리 주셔서 감사합니다.


로그인 URL을 생성하기 전에 PHP 세션을 활성화하고 Facebook이 결국 리디렉션하는 스크립트의 상단에서 쿠키를 설정하지 않고 자체적으로 잘 작동한다는 것을 발견했습니다 ( ale500의 답변에 따라 ). 이것은 sdk의 5.1 버전을 사용하고 있습니다.

두 스크립트 상단에 추가했습니다 ...

if(!session_id()) {
    session_start();
}

... 그리고 그것은 "그냥 작동했다".

다음은 나를 위해 일한 베어 본 전체 예제입니다.

auth.php

if (!session_id()) {
    session_start();
}

$oFB = new Facebook\Facebook([
    'app_id'     => FACEBOOK_APP_ID,
    'app_secret' => FACEBOOK_APP_SECRET
]);

$oHelper = self::$oFB->getRedirectLoginHelper();
$sURL = $oHelper->getLoginUrl(FACEBOOK_AUTH_CALLBACK, FACEBOOK_PERMISSIONS);

// Redirect or show link to user.

auth_callback.php

if (!session_id()) {
    session_start();
}

$oFB = new Facebook\Facebook([
    'app_id'     => FACEBOOK_APP_ID,
    'app_secret' => FACEBOOK_APP_SECRET
]);

$oHelper = self::$oFB->getRedirectLoginHelper();
$oAccessToken = $oHelper->getAccessToken();
if ($oAccessToken !== null) {
    $oResponse = self::$oFB->get('/me?fields=id,name,email', $oAccessToken);
    print_r($oResponse->getGraphUser());
}

왜?

추가 참고로, 이는 저장소의 문서에 설명되어 있습니다. 이 페이지 의 경고를보십시오 .

경고 : FacebookRedirectLoginHelper는 세션을 사용하여 CSRF 값을 저장합니다. getLoginUrl () 메서드를 호출하기 전에 세션을 활성화했는지 확인해야합니다. 일반적으로 대부분의 웹 프레임 워크에서 자동으로 수행되지만 웹 프레임 워크를 사용하지 않는 경우 session_start (); login.php 및 login-callback.php 스크립트의 맨 위에. 기본 세션 처리를 덮어 쓸 수 있습니다. 아래 확장 지점을 참조하세요.

자신의 세션 관리를 실행하거나 여러 웹 서버를 병렬로 실행하는 경우 염두에 두는 것이 중요하기 때문에이 메모를 추가합니다. 이 경우 PHP의 기본 세션 방법에 의존하는 것이 항상 작동하는 것은 아닙니다.


$ helper = $ fb-> getRedirectLoginHelper (); 뒤에이 코드를 삽입합니다.

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

이미 언급 한 훌륭한 답변이 많이 있습니다. 여기에 도움이 된 것이 있습니다.

문제가 교차 사이트 요청 위조 유효성 검사에 실패 했다는 것을 알았습니다 . FB 코드에 필수 매개 변수 "상태"가 누락 되었으며 여기에 해결책이 있습니다.

이 줄 뒤에

$helper = $fb->getRedirectLoginHelper();

아래 코드를 추가하십시오.

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

Symfony2에서 Facebook SDK를 사용하면서 Twig Extension을 작성하여 API의 데이터를 템플릿에 표시하는 동안이 오류가 발생했습니다.

나를위한 해결책 'persistent_data_handler'=>'session'은 Facebook 객체 구성 에 추가 하는 것이 었는데 , 이로 인해 상태 데이터가 메모리 대신 세션 키에 저장됩니다.

$fb = new Facebook\Facebook([
    'app_id' => 'APP_ID',
    'app_secret' => 'APP_SECRET',
    'default_graph_version' => 'v2.4',
    'persistent_data_handler'=>'session'
]);

기본적으로 기본 제공 메모리 처리기를 사용했지만 제대로 작동하지 않았습니다. 메모리 처리기가 일반 컨트롤러 / 서비스에서만 SDK를 사용할 때 작동하므로 Twig Extension 내에서 일부 함수가 호출되기 때문일 수 있습니다.

분명히 상태는 전화 할 때 설정 getLoginUrl()되며 전화 할 때 마다 검색 getAccessToken()됩니다. 저장된 상태가 반환되면 null(데이터 핸들러가 영구적 이지 않기 때문에 ) CSRF 유효성 검사가 실패합니다.

세션을 특정 방식으로 처리해야하거나 상태를 다른 곳에 저장하려는 'persistent_data_handler' => new MyPersistentDataHandler()경우 FacebookSessionPersistentDataHandler를 예로 사용하여를 사용하여 자체 핸들러를 작성할 수도 있습니다 .


이는 Facebook 라이브러리가 Facebook에서 다시 수신하는 상태 매개 변수를 기본적으로 세션에서 설정 한 매개 변수와 일치시킬 수 없을 때 발생합니다. 자체 세션 저장소를 구현하는 Laravel, Yii2 또는 Kohana와 같은 프레임 워크를 사용하는 경우 표준 Facebook 세션 구현이 작동하지 않을 수 있습니다.

이를 수정하려면 PersistentDataInterface프레임 워크의 세션 라이브러리 를 사용하여 자체 구현을 생성 하고 Facebook\Facebook생성자에 전달해야합니다 .

다음은 Facebook 의 Laravel 지속성 핸들러의 예입니다 .

use Facebook\PersistentData\PersistentDataInterface;

class MyLaravelPersistentDataHandler implements PersistentDataInterface
{
  /**
   * @var string Prefix to use for session variables.
   */
  protected $sessionPrefix = 'FBRLH_';

  /**
   * @inheritdoc
   */
  public function get($key)
  {
    return \Session::get($this->sessionPrefix . $key);
  }

  /**
   * @inheritdoc
   */
  public function set($key, $value)
  {
    \Session::put($this->sessionPrefix . $key, $value);
  }
}

생성자 매개 변수의 예 :

$fb = new Facebook\Facebook([
  // . . .
  'persistent_data_handler' => new MyLaravelPersistentDataHandler(),
  // . . .
 ]);

자세한 정보 : https://developers.facebook.com/docs/php/PersistentDataInterface/5.0.0


마지막으로 FB 코드를 살펴보면 문제가

교차 사이트 요청 위조 유효성 검사에 실패했습니다. 필수 매개 변수 "상태"누락

$_SESSION['FBRLH_state']FB가 로그인 콜백 파일을 호출 할 때 어떤 "이상한"이유 때문에 PHP 변수에 의해 유사하게 발생 합니다.

그것을 해결하기 위해 "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);

그리고 모든 FB 코드를 호출하기 전에 login-callback.php에서 :

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 시간의 작업 시간을 절약하는 데 도움이되기를 바랍니다. :) Bye, Alex.


저에게 문제는 스크립트 전에 세션을 실행하지 않았다는 것입니다.

그래서 클래스 session_start();를 인스턴스화하기 전에 추가했습니다 Facebook.


laravel 5.4에서 동일한 문제가 발생했습니다.

session_start();

스크립트 상단에 있습니다.

다음은 작동 방식에 대한 예제를 제공하는 샘플 laravel 컨트롤러 네임 스페이스입니다.

<?php
namespace App\Http\Controllers;
session_start();
use Facebook\Facebook as Facebook;
?>

이 문제는 아직 시작되지 않았기 때문에 발생하므로 스크립트 상단에 세션 시작을 추가하여 세션을 시작합니다.

누군가를 도울 수 있기를 바랍니다 ..


Facebook 객체에는 기본 PHP 세션에 액세스하기위한 세트 및 get 메소드가있는 persistentDataHandler일반적으로의 인스턴스 인 라는 인스턴스 변수 FacebookSessionPersistentDataHandler가 있습니다.

다음을 사용하여 콜백 URL을 생성 할 때 :

$loginUrl = $helper->getLoginUrl($callback_url, $permissions);

메도는 FacebookRedirectLoginHelper->getLoginUrl(), 32 문자 임의의 문자열을 생성에 추가됩니다 $loginUrl하고 사용하며 아래의 코드에 저장할 persistentDataHandler의 설정 방법을.

$_SESSION['FBRLH_' . 'state']

나중에이 $helper->getAccessToken();호출되면 URL의 상태 매개 변수가 CSRF를 방지하기 위해 동일한 세션에 저장된 것과 비교됩니다. 일치하지 않으면 예외가 발생합니다.

FacebookSDKException: 사이트 간 요청 위조 유효성 검사에 실패했습니다. 필수 매개 변수 "상태"가 없습니다.

이 모든 과정에서 네이티브 PHP 세션 기능이 제대로 설정되었는지 확인해야합니다. 추가하여 확인할 수 있습니다.

die($_SESSION['FBRLH_' . 'state']);

$loginUrl = $helper->getLoginUrl($callback_url, $permissions);

그리고 전에

$accessToken = $helper->getAccessToken();

32 자 문자열이 있는지 확인합니다.

도움이 되었기를 바랍니다.


원본 호스트 이름이 인증 된 대상 호스트 이름과 다른 경우이 오류가 발생합니다.

$loginUrl = $helper->getLoginUrl('http://MyWebSite', $permissions);

이 진술과 함께 귀하의 웹 사이트 방문자가 http://www.mywebsite.com/을 사용 하는 경우 교차 사이트 오류가 발생합니다.

원본과 대상 호스트 이름이 최종 www 접두사를 포함하여 정확히 동일한 지 확인해야합니다.

고정 버전 :

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

Symfony에서는 세션이 관리되는 방식 때문에 작동하지 않습니다.

문제를 해결하기 위해 심포니 세션에서 작동하는 새 핸들러를 만들 수 있습니다.

FacebookDataHandlerSymfony.php :

<?php

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

class FacebookDataHandlerSymfony implements PersistentDataInterface
{

    private $session;

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

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

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

}

FB 개체를 만들 때 새 클래스를 지정하기 만하면됩니다.

$this->fb = new Facebook([
            'app_id' => '1234',
            'app_secret' => '1324',
            'default_graph_version' => 'v2.8',
            'persistent_data_handler' => new FacebookDataHandlerSymfony()
        ]);

다소 늦을 수 있지만이 문제가 여전히 지속되기 때문에 다른 사람들에게 도움이되기를 바랍니다.

나는 잠시 동안이 문제가 있었고 주변을 검색하고 많은 다른 솔루션을 보았으며 그중 많은 것들이 CSRF 검사를 비활성화했습니다. 그래서 내가 읽은 모든 것이 나에게 효과적이었습니다.

내가 이해하는 바에 따르면 리디렉션 URL이 앱 설정에서 설정 한 것과 일치하지 않을 때이 오류가 발생하여 문제가 쉽게 해결되었지만 세션이 제대로 시작되지 않아 사람들이 문제를 겪는 것을 보았습니다. 두 가지 문제를 모두 다룰 것입니다.

1 단계 : 세션이 필요할 때 시작되었는지 확인합니다.

예 : fb-config.php

session_start();
include_once 'path/to/Facebook/autoload.php';

$fb = new \Facebook\Facebook([
    'app_id' => 'your_app_id',
    'app_secret' => 'your_secret_app_id',
    'default_graph_version' => 'v2.10'
]);

$helper = $fb->getRedirectLoginHelper();

페이스 북 콜백 코드가 구성 이외의 다른 파일에있는 경우 해당 파일에서도 세션을 시작하십시오.

예 : fb-callback.php

session_start();
include_once 'path/to/fb-config.php';

try {
    $accessToken = $helper->getAccessToken();
} catch (\Facebook\Exceptions\FacebookResponseException $e) {
    echo "Response Exception: " . $e->getMessage();
    exit();
} catch (\Facebook\Exceptions\FacebookSDKException $e) {
    echo "SDK Exception: " . $e->getMessage();
    exit();
}

/** THE REST OF YOUR CALLBACK CODE **/

이제 내 실제 문제가 해결되었습니다.

3 단계 : 앱 설정에서 리디렉션 URL을 설정합니다.

Facebook 로그인 앱 설정에서 fb-callback.php 파일을 가리키는 URL을 추가해야하는 유효한 OAuth 리디렉션 URI로 이동합니다.

http://example.com/fb-callback.php

AND ALSO

http://www.example.com/fb-callback.php

그런 다음 리디렉션 URL을 다음과 같이 설정하십시오.

$redirectURL = "http://".$_SERVER['SERVER_NAME']."/fb-callback.php";
$permissions = ['email'];
$fLoginURL = $helper->getLoginUrl($redirectURL, $permissions);

www가 있거나없는 이유와 SERVER_NAME을 사용하는 이유는 무엇입니까?

유효한 OAuth 리디렉션 URI 가 코드의 리디렉션 URL과 일치해야하기 때문에 앱 설정에서 OAuth 리디렉션 만 http://example.com/fb-callback.php 로 설정하고 $ redirectURL을 http 로 설정합니다 . //example.com/fb-bacllback.php 를 사용하여 일치하도록 만들었지 만 사용자가 http://www.example.com으로 사이트를 입력 하면 사용자는 Facebook SDK 오류 : 사이트 간 요청 위조 유효성 검사에 실패했습니다. 사용자가있는 URL이 설정 한 것과 정확히 일치하지 않기 때문에 영구 데이터에서 필수 매개 변수 "상태"가 누락되었습니다 . 왜? 나는 이상한 생각이 없다.

내 접근 방식에서는 사용자가 http://example.com 또는 http://www.example.com 으로 사이트를 입력 하면 항상 앱 설정에서 설정 한 것과 일치합니다. 왜? $ _SERVER [ 'SERVER_NAME']은 사용자가 브라우저에 URL을 입력 한 방법에 따라 www가 있거나없는 도메인을 반환하기 때문입니다.

이것은 내 발견이며 이것은 CSRF 검사를 제거하지 않고 지금까지 문제가없는 유일한 일입니다.

이게 도움이 되길 바란다.


나를 위해 쉬운 수정. 나는 변했다 :

$loginUrl = $helper->getLoginUrl('http://www.MYWEBSITE.ca/index_callback.php', $permissions);

에:

$loginUrl = $helper->getLoginUrl('http://MYWEBSITE.ca/index_callback.php', $permissions);

제거하면 'www'문제가 해결되었습니다.


새로운 상태로 세션을 설정할 수 있습니다.

<?php
if(isset($_GET['state'])) {
      if($_SESSION['FBRLH_' . 'state']) {
          $_SESSION['FBRLH_' . 'state'] = $_GET['state'];
      }
}
?>

제 경우에는 오류를 확인하고 코드 실행으로 해결하는 오류를 발견했습니다.

date_default_timezone_set('Europe/Istanbul');

스크립트 전에. 매력처럼 작동했습니다. 위치 확인 : timezones.europe.php


원본 호스트 이름이 대상 호스트 이름과 다른 경우 오류가 발생합니다. 방문자가 URL 주소 상자에 " http://www.website.com "과 다른 " http://website.com "을 입력 한 경우. session_start () 앞의 맨 위에 다음 코드를 추가하여 올바른 URL로 리디렉션합니다.

  if($_SERVER['HTTP_HOST']!=='www.website.com'){
  header('location: http://www.website.com');
  }

나를 위해 작동하는 Yii2 솔루션 :

use Facebook\PersistentData\PersistentDataInterface;
use Yii;

class PersistentDataHandler implements PersistentDataInterface
{
    /**
     * @var string Prefix to use for session variables.
     */
    protected $sessionPrefix = 'FBRLH_';

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

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

"www"를 추가하는 것을 잊었 기 때문에 동일한 오류가 발생했습니다. 발신자 주소로. 클라이언트 -OAuth 설정에 올바른 이름이 있어야합니다.


이것은 많은 사람들이 FB Api에서 직면하는 일반적인 문제입니다. 이것은 세션 문제 일뿐입니다. 이 문제를 해결하려면 다음과 같은 코드를 추가하십시오.

On callback script usually fb-callback.php add "session_start();" just before you include the facebook autoload file. and then "$_SESSION['FBRLH_state']=$_GET['state'];" after the "$helper = $fb->getRedirectLoginHelper();" line.

Example :

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

Might help someone, who is using Javascript Helper in frontend for authenticating the user and in PHP one is trying to to extract access_token from Redirect Login Helper. So use following

getJavaScriptHelper();

instead of

getRedirectLoginHelper();

SOLUTION FOR INTERMITTENT PROBLEMS

I was a) redirecting to Facebook login link, b) redirecting from login.php to main.php. Users would travel to main.php and a few other pages, then click back back back in browser.

Eventually, they would hit login.php with a bunch of creds posted to it, but Facebook removes the $_SESSION['FBRLH_state'] after a single success, so even though it had the proper $_GET['state'], it would error out.

The solution is to a) track internally if the user is logged in and avoid the repeat Facebook logic in login.php, OR b) keep track of all recently valid state parameters for that particular user (in a session perhaps) which were set by Facebook and if the $_GET['state'] is in that array, then do this:

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

In this case you can do this safely without breaking CSRF protection.


For me setting the session state worked

Complete code ( in the redirect url php )

$accessToken = '';

$helper = $fb->getRedirectLoginHelper();

if(isset($_GET['state'])){

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


try {
    $accessToken = $helper->getAccessToken();
} catch ( Facebook\Exceptions\FacebookResponseException $e ) {
    // When Graph returns an error
    echo 'Graph returned an error: ' . $e->getMessage();

}

For me the problem was different; (I was stupid) I had a popup window with Facebook login and again Facebook login buttons in Login/Signup page.

  • Whenever i click the Facebook button in the popup from other pages it worked fine.
  • But, when i click the Facebook button in the popup from Login/Signup page, it would not work.

The reason was i had re-instantiated the Facebook and getRedirectLoginHelper objects. I had to comment out these statements in Login/Signup pages, as it was already available.

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

is not the way to go. Although it worked.


if you keep to see the error, just clean your browser cache. When I've fixed the problem using the enobrev solution, I was continuing to experience the error. After a while I've understood that I needed to clean the cache and after I've restarted the browser it worked!

참고URL : https://stackoverflow.com/questions/32029116/facebook-sdk-returned-an-error-cross-site-request-forgery-validation-failed-th

반응형