我使用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的问题不同,因为在我的情况下它是随机的。
答案 0 :(得分:64)
我昨晚遇到了这个问题并使用以下解决方案解决了这个问题。
有关我的问题的更多信息,我已经
AbstractProvider.php第182行中的InvalidStateException
在函数handleProviderCallback()
中,当它从Facebook登录重定向时。它似乎和你的问题一样。
此外,我发现在没有www
的情况下打开网站时出现问题。当我用www.mysite.com
打开我的网站时 - 没问题。起初我认为我的问题是随机的,直到我得到 Chris Townsend 回答这个问题的线索 - 非常感谢你。
解决方案
config/session.php
'domain' => null,
我对'domain' => 'mysite.com'
进行了更改。'php artisan cache:clear'
和'composer dump-autoload'
之后,我可以同时登录www.mysite.com
和mysite.com
在完成这些修改后,请务必在测试时从浏览器中删除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)
InvalidStateException
是一个红色鲱鱼,真正的根本原因是其他一些错误。我花了大约12个小时才意识到我还没有在模型的$fillable
数组中添加新字段。$provider->user()
每个请求只能被调用一次 ,因为inside of that function调用hasInvalidState()
,然后removes从会话中获取“状态”条目。我花了几个小时才意识到我碰巧要多次调用$provider->user()
,而我本应该只调用一次并将结果保存到变量中。答案 6 :(得分:1)
如果此问题在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:clear
和composer 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;
}
// ...
}