跨站点请求伪造验证失败。缺少 Laravel Sammyk/Facebook 包所需的参数“状态”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30365371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:35:46  来源:igfitidea点击:

Cross-site request forgery validation failed. Required param "state" missing Laravel Sammyk/Facebook package

phpfacebook-graph-apilaravellaravel-5

提问by KillABug

I am working with the SammyK/Facebook package and facing an issue with facebook login over CSRF. Earlier it worked fine,but later I had to disable the CSRF protection in my kernel.php for smooth working of API. Now I have it updated and added the below lines in the middleware

我正在使用 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);
  }

So this allows web and api to work as expected,but since I had disabled the csrf I get the Cross-site request forgery validation failed. Required param "state" missing error when I do a FB login. I tried to debug and found in the FacebookRedirectLoginHelper the function validateCsrf()does not get the savedstate $savedState = $this->persistentDataHandler->get('state');
I am not sure how to resolve this as ideally it should work now.I tried printing both the $state and $savedState and I get $savedState as null.

所以这允许 web 和 api 按预期工作,但由于我禁用了 csrf,我得到跨站点请求伪造验证失败。当我进行 FB 登录时,必需的参数“状态”丢失错误。我尝试调试并在 FacebookRedirectLoginHelper 中发现该函数validateCsrf()没有得到 savestate$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()
     );
  } 

回答by ale500

Finally, looking into FB code, I discovered that the problem "Cross-site request forgery validation failed. Required param “state” missing" and similars are caused by PHP variable $_SESSION['FBRLH_state'] that for some "strange" reason when FB call the login-callback file.

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

To solve it I store this variable "FBRLH_state" AFTER the call of function $helper->getLoginUrl(...). Is very important to do only after the call of this function due to is inside this function when the variable $_SESSION['FBRLH_state'] is populated.

为了解决这个问题,我在调用函数 $helper->getLoginUrl(...) 之后存储了这个变量“FBRLH_state”。只有在调用此函数后才执行此操作非常重要,因为在填充变量 $_SESSION['FBRLH_state'] 时位于该函数内部。

Below an example of my code in the login.php:

下面是我在 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);

And in the login-callback.php before calling all FB code:

并在调用所有 FB 代码之前的 login-callback.php 中:

foreach ($_COOKIE as $k=>$v) {
    if(strpos($k, "FBRLH_")!==FALSE) {
        $_SESSION[$k]=$v;
    }
}

Last, but not least, remember also to include code for PHP session so..

最后但并非最不重要的一点,请记住还要包含 PHP 会话的代码,以便..

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

I hope this response can help you to save 8-10 hours of work :) Bye, Alex.

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

回答by italo.portinho

For those who are using Code Igniter , you will have to autoload the session library.

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

Change your application/config/autoload.php , libraries must include 'session':

更改您的 application/config/autoload.php ,库必须包含“会话”:

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

回答by fobus

This is was my head ache, then I found an easy way to fix it.

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

find config/session.php and change

找到 config/session.php 并更改

'expire_on_close' => false,

'expire_on_close' => false,

to

'expire_on_close' => true,

'expire_on_close' => true,