Laravel Socialite:InvalidStateException

时间:2015-06-05 07:32:51

标签: php facebook laravel laravel-5

我使用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的问题不同,因为在我的情况下它是随机的。

26 个答案:

答案 0 :(得分:64)

我昨晚遇到了这个问题并使用以下解决方案解决了这个问题。

有关我的问题的更多信息,我已经

  

AbstractProvider.php第182行中的InvalidStateException

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

此外,我发现在没有www的情况下打开网站时出现问题。当我用www.mysite.com打开我的网站时 - 没问题。起初我认为我的问题是随机的,直到我得到 Chris Townsend 回答这个问题的线索 - 非常感谢你。

解决方案

  1. 转到您的www root,检查laravel文件config/session.php
  2. 检查会话会话Cookie域 默认配置为'domain' => null,我对'domain' => 'mysite.com'进行了更改。
  3. 'php artisan cache:clear''composer dump-autoload'之后,我可以同时登录www.mysite.commysite.com
  4. 在完成这些修改后,请务必在测试时从浏览器中删除Cookie。旧饼干仍然会产生问题。

答案 1 :(得分:38)

已解决:

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

答案 2 :(得分:10)

<强> TL;博士

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

   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对于通过谷歌传递数据非常有用:

  

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

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

答案 3 :(得分:2)

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

在我的情况下,由于此文件夹在新的Laravel项目中为空,因此在最初提交到GIT存储库期间已将其遗漏。之后我在生产服务器上手动创建它,但显然访问权限错误,因此会话驱动程序无法写入(设置为'file'时)。

答案 4 :(得分:2)

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

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

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

对我有用。希望对您有帮助

答案 5 :(得分:1)

有2个主要的“陷阱”,现有答案均未解决。

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

答案 6 :(得分:1)

2020/04

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

如果您的应用依赖于有效的跨站点Cookie,则需要在Cookie中添加“ SameSite = None; Secure”。在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版本。

进一步阅读:

答案 7 :(得分:1)

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,

答案 8 :(得分:1)

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

答案 9 :(得分:1)

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

                                           file_name      data        date
0  09066271_142468576_1_Haha_-Haha-haha_2016-10-0...  09066271  2016-10-07
1  09014271_142468576_1_Haha_-Haha-haha_2013-02-1...  09014271  2013-02-18

答案 10 :(得分:1)

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

php artisan cache:clear

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

答案 11 :(得分:0)

我遇到了类似的问题,

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仍然会产生问题。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

最后我通过以下方式解决了:

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

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

答案 14 :(得分:0)

2020年10月

对我来说,我有

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

所以我转换了我的代码

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

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

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

答案 15 :(得分:0)

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

然后清理配置并缓存:

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

清除Cookie(或在隐身模式下运行)

由于默认情况下Facebook允许localhost重定向,因此您无需在fb应用中将网址列入白名单。

答案 16 :(得分:0)

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

答案 17 :(得分:0)

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;
}

答案 18 :(得分:0)

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

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

答案 19 :(得分:0)

我修复了这个只是禁用SESSION DRIVER作为数据库...文件驱动程序在我试图解决这个问题后工作正常...

答案 20 :(得分:0)

callback()方法内的控制器上

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

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

答案 21 :(得分:0)

如果您仍然需要帮助,可以使用我的代码,它对我有用。您只需创建两个路由并更新users表。别忘了让密码可以为空,因为你没有从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');

}

答案 22 :(得分:0)

获得解决方案-更新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());
    }

答案 23 :(得分:0)

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

答案 24 :(得分:-1)

此问题与上述许多解决方案无关,就像在config/services.php和Twitter上将回调URL从'http://localhost:8000/callback/twitter更改为http://127.0.0.1:8000/callback/twitter一样简单在您的Twitter应用程序上设置的应用程序。

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

答案 25 :(得分:-4)

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

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

    // ...
}

我停止抛出新的InvalidStateException并调用重定向函数:

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

    // ...
}