跨站点请求伪造验证失败。必需的参数"州"缺少Laravel Sammyk / Facebook软件包

时间:2015-05-21 05:37:22

标签: php facebook-graph-api laravel laravel-5

我正在使用SammyK / Facebook软件包,并面临着通过CSRF登录facebook的问题。之前它运行良好,但后来我不得不在我的kernel.php中禁用CSRF保护,以便顺利运行API。现在我更新了它并在中间件

中添加了以下行
  public function handle($request, Closure $next) {
   $skip = array(
              'api/v1/signup',
              'api/v1/login',
              'api/v1/addContacts',
              'api/v1/email'
             );
    foreach ($skip as $key => $route) {
      //skip csrf check on route
      if($request->is($route)){
          return parent::addCookieToResponse($request, $next($request));
      }
   }
   return parent::handle($request, $next);
  }

因此,这允许web和api按预期工作,但由于我已禁用csrf,因此我得到跨站点请求伪造验证失败。必需的参数"州"我登录FB时错过了错误。我尝试调试并在FacebookRedirectLoginHelper中找到函数validateCsrf()没有得到保存状态$savedState = $this->persistentDataHandler->get('state');
我不知道如何解决这个问题,因为理想情况下它现在可以正常工作。我尝试打印$ state和$ savedState,并将$ savedState视为null。

    class FacebookController extends Controller {
     public function fbConnect(LaravelFacebookSdk $fb)
     {
      // Obtain an access token.
     try {
     $token = $fb
        ->getRedirectLoginHelper()
       ->getAccessToken();
     } catch (Facebook\Exceptions\FacebookSDKException $e) {
          dd($e->getMessage());
    }
   // Access token will be null if the user denied the request
    // or if someone just hit this URL outside of the OAuth flow.
 if (! $token) {
    // Get the redirect helper
 $helper = $fb->getRedirectLoginHelper();

   if (! $helper->getError()) {
        abort(403, 'Unauthorized action.');
   }

   // User denied the request
    dd(
       $helper->getError(),
       $helper->getErrorCode(),
       $helper->getErrorReason(),
       $helper->getErrorDescription()
     );
  } 

3 个答案:

答案 0 :(得分:6)

最后,看一下FB代码,我发现问题"跨站点请求伪造验证失败。必需的参数“状态”缺失"和类似物是由PHP变量$ _SESSION [' FBRLH_state']引起的,对某些人而言,#34;奇怪的" 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);

在调用所有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个小时的工作:) 再见,亚历克斯。

答案 1 :(得分:1)

对于使用Code Igniter的用户,您必须自动加载会话库。

更改您的application / config / autoload.php,库必须包含'session':

$autoload['libraries'] = array('session');

答案 2 :(得分:0)

这是我的头疼,然后我找到了一种简单的方法来解决它。

找到config / session.php并更改

'expire_on_close' => false,

'expire_on_close' => true,