【问题标题】:Laravel Socialite: InvalidStateExceptionLaravel 社交名流:InvalidStateException
【发布时间】:2015-08-20 01:38:48
【问题描述】:

我正在使用 Laravel Socialite 在网站上添加 Facebook 连接按钮。有时,我在回调时遇到此错误:

exception 'Laravel\Socialite\Two\InvalidStateException' 
in /example/vendor/laravel/socialite/src/Two/AbstractProvider.php:161

我不知道这是什么意思,也没有发现任何关于这个错误的信息。真正的问题是它似乎是一个随机异常(不明白为什么会发生)。那么这个错误意味着什么以及如何避免呢?

这似乎与Laravel 5 geting InvalidStateException in AbstractProvider.php 的问题不同,因为在我的情况下它是随机的。

【问题讨论】:

  • 我认为这可能是问题所在,stackoverflow.com/a/29975589/1430587
  • 真的很接近,但我认为这不是同一个问题,因为随机性
  • 我从不同的 url 路径访问我的应用程序时遇到了这个问题,例如如果我尝试从 www.mysite.com/ 登录,它会起作用,但如果我通过访问 http:\\mysite.com 进行访问,则会出现该错误。
  • 问题是它是真的随机还是只是看起来随机(人类在识别真正随机的现象方面非常糟糕)。当抛出这个异常时,我会开始记录 everything,看看是否出现了某种模式。鉴于其他人(@ChrisTownsend 和我自己,在上面引用的答案中)已经确定这可能与会话 cookie 问题有关,我将从那里开始。

标签: php facebook laravel laravel-5


【解决方案1】:

我遇到了同样的问题,只是因为使用 127.0.0.1:8000/ 而不是 http://localhost:8000/

【讨论】:

  • 在两者之间,您改变了 两个 的东西:明确指定方案通过 IPv4 与名称指定主机。你能缩小原因吗?
【解决方案2】:

我终于解决了:

.env 文件中的重定向 URL 应与 Google 开发者帐户中的 URL 相同

仔细检查您的重定向网址。

【讨论】:

    【解决方案3】:

    2020 年 10 月

    对我来说,我有

    …\vendor\laravel\socialite\src\Two\AbstractProvider.php209
    

    所以我从

    转换了我的代码
    $user = Socialite::driver('facebook')->user();
    

    $user = Socialite::driver('facebook')->stateless()->user();
    

    我不必运行任何缓存清除,但我确实删除了 cookie,但我不确定你是否必须这样做。

    【讨论】:

    • 您能解释一下为什么stateless() 可以解决这个问题吗?它也对我有用,但我想知道为什么需要它以及为什么要修复它。谢谢。
    【解决方案4】:

    对我来说,解决方案是将APP_URL 设置为http://localhost:8000 而不是http://127.0.0.1:8000(假设您在8000 端口上运行您的服务器)。

    然后,清理配置和缓存:

    • php artisan config:clear
    • php artisan cache:clear

    清除 cookie(或以隐身模式运行)

    由于 facebook 默认允许 localhost 重定向,因此您不必将 fb 应用中的 url 列入白名单。

    【讨论】:

      【解决方案5】:

      我在这两天堆积起来,将'driver' => env('SESSION_DRIVER', 'file')更改为'driver' => env('SESSION_DRIVER', 'cookie')为我工作

      【讨论】:

        【解决方案6】:

        Laravel:7.10.3

        PHP:7.3.15

        我也遇到了这个问题。不知何故,建议的解决方案并没有帮助我解决问题。

        在花了很多时间尝试修复我的代码之后,我认为这也可能与我的 php-fpm -> nginx 设置有关。

        更改我的 nginx 配置后,现在可以通过 Facebook 登录。

        不正确的配置:

        location ~ \.(php|phar)(/.*)?$ {
            fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;
            fastcgi_intercept_errors on;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO $fastcgi_path_info;
            fastcgi_pass   unix:/var/run/php-fpm/www.sock;
        }
        
        location / {
           try_files $uri $uri/ /index.php;
        }
        

        正确的配置

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php-fpm/www.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
        

        【讨论】:

          【解决方案7】:

          在我的场景中,我在 localhost 上运行了两个 Laravel 应用程序,一个实现了护照,并利用社交名流对护照应用程序进行身份验证。我忘记在.env 中设置APP_NAME,所以每个应用程序都在写入相同的lavarel_session cookie,因此社交名流应用程序无法从会话中提取状态值,因为其他应用程序已经踩到饼干。

          如果您的应用程序在同一域上运行并且使用您自己的提供程序,请确保在设置应用程序时在 .env 中设置 APP_NAME 值。

          【讨论】:

            【解决方案8】:

            2020/04

            如果您在 2020 年 2 月左右出现此问题,则很有可能与 2020 年 2 月上旬发布的 Google Chrome 80+ 版本有关。 我不会假装我完全理解了这个问题,但简而言之,如果没有指定 SameSite 属性,Google Chrome 现在默认将 cookie 视为 SameSite=Lax。

            如果您的应用依赖于工作的跨站点 cookie,您需要将“SameSite=None; Secure”添加到您的 cookie。在 Laravel 5.5+ 中,您可以通过会话配置的两个更改来实现:

            config/session.php

            'secure' => env('SESSION_SECURE_COOKIE', true), // or set it to true in your .env file
            

            ...

            'same_site' => "none",
            

            早期的 Laravel 版本显然不支持“none”值。但是现在,如果这会产生一个奇怪的错误检查 /vendor/symfony/http-foundation/Cookie.php 并确保有一个 SAMESITE_NONE 常量。如果它不存在,您可能需要升级您的 Laravel 版本。

            延伸阅读:

            【讨论】:

              【解决方案9】:

              Laravel 6.16.0
              php 7.4.2

              我遇到了这个确切的问题。原来我最近将same_site 更改为strict 并且社交名流抛出了InvalidStateException 异常。然后我把它改回null,一切正常。

              /*
                  |--------------------------------------------------------------------------
                  | Same-Site Cookies
                  |--------------------------------------------------------------------------
                  |
                  | This option determines how your cookies behave when cross-site requests
                  | take place, and can be used to mitigate CSRF attacks. By default, we
                  | do not enable this as other CSRF protection services are in place.
                  |
                  | Supported: "lax", "strict"
                  |
                  */
              
                  'same_site' => null,
              

              【讨论】:

                【解决方案10】:

                callback() 方法中的控制器上

                $user = $service->createOrGetUser(Socialite::driver('facebook')->user());

                $user = $service->createOrGetUser(Socialite::driver('facebook')->stateless()->user());

                【讨论】:

                  【解决方案11】:

                  只有当我在手机上打开我的网站并通过手机上的 facebook 应用程序打开对话框时,我才会遇到同样的情况。

                  我认为: 发生这种情况是因为打开 Facebook 应用程序以从 Facebook API 获取响应使我们丢失了一些 cookie。它变得无国籍。 然后我只是使用 socialite 已经被制作的选项来避免 stateless 请求。

                  $user = Socialite::driver($provider)->stateless()->user();
                  

                  它对我有用。希望对你有帮助

                  【讨论】:

                    【解决方案12】:

                    这个问题与上面的许多解决方案无关,就像在你的config/services.php 和在你的推特上设置的推特应用程序中将你的回调 URL 从“http://localhost:8000/callback/twitter”更改为 http://127.0.0.1:8000/callback/twitter 一样简单应用。

                    URL 中的http://localhost 是问题,替换为http://127.0.0.1

                    【讨论】:

                      【解决方案13】:

                      现有的答案都没有解决 2 个主要的“陷阱”。

                      1. 有时InvalidStateException 是一个红鲱鱼,真正的根本原因是其他一些错误。有一次我花了大约 12 个小时才意识到我没有向模型中的 $fillable 数组添加新字段。
                      2. 除非你 disable session state verification(这里的其他答案似乎希望你这样做,但不是每个人都愿意这样做),$provider->user() 每个请求只能调用一次 因为inside of that function 调用hasInvalidState(),然后removes 来自会话的“状态”条目。我花了几个小时才意识到我碰巧多次调用$provider->user(),而我应该只调用一次并将结果保存到变量中。

                      【讨论】:

                        【解决方案14】:

                        在我的情况下,这是由于 User 类中的 $fillable 数组中缺少参数引起的。当我添加所有缺少的参数时,它开始正常工作..

                        【讨论】:

                          【解决方案15】:

                          找到解决方案 - 2018 年 11 月更新

                          public function redirectToGoogle(Request $request)
                          {
                              /**
                               * @var GoogleProvider $googleDriver
                               */
                              $googleDriver = Socialite::driver("google");
                              return $googleDriver->redirect();
                          }
                          
                          public function fromGoogle(Request $request)
                          {
                              try {
                          /*
                          Solution Starts ----
                          */
                                  if (empty($_GET)) {
                                      $t = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
                                      parse_str($t, $output);
                                      foreach ($output as $key => $value) {
                                          $request->query->set($key, $value);
                                      }
                                  }
                          /*
                          Solution Ends ----
                          */
                                  /**
                                   * @var GoogleProvider $googleDriver
                                   */
                                  $googleDriver = Socialite::driver("google");
                                  print_r($googleDriver->user());
                              } catch (\Exception $e) {
                                  print_r($e->getMessage());
                              }
                          

                          【讨论】:

                            【解决方案16】:

                            我有类似的问题,我有

                            InvalidStateException in AbstractProvider.php line 182
                            

                            在函数handleProviderCallback() 中,当它从 Facebook 登录重定向回来时。好像和你的问题一样。

                            此外,我发现在没有www 的情况下打开网站时会出现问题。当我使用www.mysite.com 打开我的网站时 - 没问题。起初我认为我的问题是随机的,直到我从 Chris Townsend 对问题的回答中得到线索。

                            解决方案

                            转到您的 www 根目录,检查 laravel 文件 config/session.php。检查会话Session Cookie Domain。默认配置是

                            'domain' => null,
                            

                            我做了更改

                            'domain' => 'mysite.com' 
                            

                            php artisan cache:clearcomposer dump-autoload 之后,我可以从 www.mysite.com 和 mysite.com 登录而没有问题

                            在完成这些修改后进行测试时,请务必从浏览器中删除您的 cookie。旧的 cookie 仍然会产生问题。

                            【讨论】:

                            • 如果针对此问题提供的答案不能解决您的问题,请提出一个新问题。 :-)
                            【解决方案17】:

                            这为我解决了
                            $request->session()->put('state',Str::random(40)); $user = Socialite::driver('github')->stateless()->user();

                            【讨论】:

                              【解决方案18】:

                              我只是在使用 facebook 应用程序而不是浏览器中的 facebook 通过移动网络登录时遇到此错误。 facebook 应用程序在登录后使用 facebook 浏览器而不是您当前的浏览器,因此不知道之前的状态。

                              try {
                                  $socialite = Socialite::driver($provider)->user();
                              } catch (InvalidStateException $e) {
                                  $socialite = Socialite::driver($provider)->stateless()->user();
                              }
                              

                              【讨论】:

                                【解决方案19】:

                                我遇到了同样的问题,我只是清除了缓存来解决这个问题。我刚刚运行了这个命令并再次开始了这个过程。

                                php artisan cache:clear
                                

                                我希望这个答案可以帮助别人。

                                【讨论】:

                                  【解决方案20】:

                                  我想与您分享我的解决方案。我转到我的AbstractProvider.php 文件并在问题行中

                                  public function user()
                                  {
                                      if ($this->hasInvalidState()) {
                                          throw new InvalidStateException;
                                      }
                                  
                                      // ...
                                  }
                                  

                                  我停止 throw new InvalidStateException 并像这样调用重定向函数:

                                  public function user()
                                  {
                                      if ($this->hasInvalidState()) {
                                          $this->redirect();
                                          // throw new InvalidStateException;
                                      }
                                  
                                      // ...
                                  }
                                  

                                  【讨论】:

                                  • 这只是在无限循环中启动身份验证,对吗? redirect() 是流程的第一部分,而user() 是第二部分...
                                  【解决方案21】:

                                  已解决:

                                  Socialite::driver('google')->stateless()->user()
                                  

                                  【讨论】:

                                  • 当我这样做时,用户在重定向后没有登录。我使用了 auth()->login($user);等等……
                                  • 请务必将stateless() 也添加到您的重定向行,否则重定向后您可能无法登录。 Socialite::driver('google')->stateless()->redirect()
                                  • 为我工作,以防我必须从一个子域登录并重定向回另一个子域。
                                  • 我应该在哪里插入Socialite::driver('google')->stateless()->user()?在什么文件里?谢谢。
                                  • 它有什么作用,为什么需要它?
                                  【解决方案22】:

                                  tl;dr

                                  如果您需要读取第三方服务返回的给定参数state,您可以使用stateless 方法设置Socialite 以避免此检查:

                                     Socialite::driver($provider)->stateless();
                                  

                                  我认为社交名流已经准备好避免这个问题。

                                  https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L77

                                   /**
                                   * Indicates if the session state should be utilized.
                                   *
                                   * @var bool
                                   */
                                  protected $stateless = false;
                                  

                                  https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L374

                                  /**
                                   * Indicates that the provider should operate as stateless.
                                   *
                                   * @return $this
                                   */
                                  public function stateless()
                                  {
                                      $this->stateless = true;
                                      return $this;
                                  }
                                  

                                  https://github.com/laravel/socialite/blob/2.0/src/Two/AbstractProvider.php#L222

                                  /**
                                   * Determine if the current request / session has a mismatching "state".
                                   *
                                   * @return bool
                                   */
                                  protected function hasInvalidState()
                                  {
                                      if ($this->isStateless()) {
                                          return false; // <--------
                                      }
                                      $state = $this->request->getSession()->pull('state');
                                      return ! (strlen($state) > 0 && $this->request->input('state') === $state);
                                  }
                                  

                                  例如,state 对于通过 google 传递数据非常有用:

                                  参数:状态(任何字符串)
                                  提供任何可能对您有用的状态 收到回复后申请。谷歌授权 服务器往返此参数,因此您的应用程序接收 它发送的相同值。可能的用途包括将用户重定向到 您站点中的正确资源和跨站点请求伪造 缓解措施。

                                  参考:https://developers.google.com/identity/protocols/OAuth2UserAgent#overview

                                  【讨论】:

                                  • 这对我有用 Socialite::driver($provider)->stateless();
                                  • 这可能很危险,正如文档所说 Possible uses include [...] cross-site-request-forgery mitigations
                                  • @HarryBosh 您插入了文件的哪个部分?在什么文件里?谢谢。
                                  【解决方案23】:

                                  同时检查您的storage/framework/sessions 文件夹的访问权限。

                                  在我的例子中,由于这个文件夹在新的 Laravel 项目中是空的,所以在最初提交到 GIT 存储库时它被遗漏了。之后我在生产服务器上手动创建了它,但显然访问权限错误,因此会话驱动程序不可写(设置为'file'时)。

                                  【讨论】:

                                    【解决方案24】:

                                    我解决了这个问题,只是将 SESSION DRIVER 禁用为数据库...文件驱动程序在尝试修复此问题数小时后对我来说工作正常...

                                    【讨论】:

                                      【解决方案25】:

                                      我昨晚遇到了这个问题,用下面的方法解决了。

                                      关于我的问题的更多信息,我有

                                      AbstractProvider.php 第 182 行中的 InvalidStateException

                                      在函数handleProviderCallback() 中,当它从 Facebook 登录重定向回来时。好像和你的问题一样。

                                      此外,当我打开没有www 的网站时,我发现我的问题出现了。当我用www.mysite.com 打开我的网站时 - 没问题。起初我认为我的问题是随机的,直到我从 Chris Townsend 对问题的回复中得到线索 - 非常感谢。

                                      解决方案

                                      1. 进入你的www根目录,检查laravel文件config/session.php
                                      2. 检查会话会话 Cookie 域 默认配置是'domain' =&gt; null,我改成了'domain' =&gt; 'mysite.com'
                                      3. 'php artisan cache:clear''composer dump-autoload' 之后,www.mysite.commysite.com 都可以正常登录

                                      在完成这些修改后进行测试时,请务必从浏览器中删除您的 cookie。旧的 cookie 仍然会产生问题。

                                      【讨论】:

                                      • 正确,但适用于在 localhost 和 Chrome 上工作的人。请记住,Chrome 现在确实为 localhost 设置了 cookie,因此问题仍然存在,以解决将有效(带有点的)域名添加到主机文件,然后相应地更改 laravel 配置文件。
                                      • 如果是本地主机,我应该为域写什么?
                                      • 需要在config/session.php中同时改变'domain'和'cookie'的值。否则用户将遇到意外的登录问题。请看stackoverflow.com/questions/33260856/…
                                      • 您先生是救生员!谢谢
                                      • 我刚刚将 www 重定向到 .htaccess 中的非 www。我使用了this article,它也将 HTTP 重定向到 HTTPS。
                                      【解决方案26】:

                                      如果您仍然需要帮助,可以使用我的代码,它对我有用。您只需要创建两个路由并更新用户表。不要忘记让密码可以为空,因为你不会从 facebook 用户那里得到一个 我的控制器中的代码:

                                      public function redirectToProvider()
                                      {
                                          return Socialize::with('facebook')->redirect();
                                      }
                                      
                                      public function handleProviderCallback(User $user)
                                      {
                                          $money = Socialize::with('facebook')->user();
                                      
                                          if(User::where('email', '=', $money->email)->first()){
                                          $checkUser = User::where('email', '=', $money->email)->first();
                                          Auth::login($checkUser);
                                          return redirect('home');
                                           } 
                                      
                                          $user->facebook_id = $money->getId();
                                          $user->name = $money->getName();
                                          $user->email = $money->getEmail();
                                          $user->avatar = $money->getAvatar();
                                          $user->save();
                                      
                                          Auth::login($user);
                                          return redirect('home');
                                      
                                      }
                                      

                                      【讨论】:

                                        猜你喜欢
                                        • 2018-05-11
                                        • 2018-06-25
                                        • 1970-01-01
                                        • 2016-01-29
                                        • 2019-12-17
                                        • 1970-01-01
                                        • 2021-02-10
                                        • 2016-09-11
                                        • 1970-01-01
                                        相关资源
                                        最近更新 更多