php - 跨站点请求伪造验证失败。所需参数 "state"缺少 Laravel Sammyk/Facebook 包

标签 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 登录时,必需的参数“state”丢失错误。我尝试调试并在 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()
     );
  } 

最佳答案

最后,查看 FB 代码,我发现问题“跨站点请求伪造验证失败。必需的参数“state”缺失”和类似的问题是由 PHP 变量 $_SESSION['FBRLH_state'] 引起的,对于一些“奇怪的” "FB 调用登录回调文件的原因。

为了解决这个问题,我在函数 $helper->getLoginUrl(...) 调用之后存储了这个变量“FBRLH_state”。仅在调用此函数之后执行此操作非常重要,因为在填充变量 $_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 session 的代码,以便......

if(!session_id()) {
    session_start();
}
...
...
...
...
<?php session_write_close() ?>

我希望这个回复可以帮助您节省 8-10 个小时的工作:) 再见,亚历克斯。

关于php - 跨站点请求伪造验证失败。所需参数 "state"缺少 Laravel Sammyk/Facebook 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30365371/

相关文章:

php - 我如何使用 PHP 实现这种情况?

facebook - 基于光标的分页 - 如果 "before"或 "after"对象被删除怎么办?

mysql - 违反完整性约束 : 1048 Column 'post_id' cannot be null

php - Laravel 5 无需密码登录

php - Mysql查询,更具体地说是用Laravel eloquent

php - PHP 中同名的不同元素

php - 保护 iOS 到 Web 服务通信的安全

javascript - 在 PHP 中将本地镜像 blob 转换为 base64

ios - 如何使用 FB SDK 限制当前用户检索页面喜欢

java - 使用图形 API 获取用户相册中的照片的链接是什么?