[英]Laravel Socialite: InvalidStateException
我正在使用 Laravel Socialite 在網站上添加 Facebook 連接按鈕。 有時,我在回調時遇到此錯誤:
exception 'Laravel\Socialite\Two\InvalidStateException'
in /example/vendor/laravel/socialite/src/Two/AbstractProvider.php:161
我不知道這是什么意思,也沒有發現任何關於這個錯誤的信息。 真正的問題是它似乎是一個隨機異常(不明白為什么會發生)。 那么這個錯誤意味着什么以及如何避免呢?
它似乎與Laravel 5 在 AbstractProvider.php 中獲取 InvalidStateException 不同,因為在我的情況下它是隨機的。
我昨晚遇到了這個問題並使用以下解決方案解決了它。
關於我的問題的更多信息,我有
AbstractProvider.php 第 182 行中的 InvalidStateException
在函數handleProviderCallback()
當它從 Facebook 登錄handleProviderCallback()
回來時。 好像和你的問題一樣。
此外,我發現當我在沒有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。 舊的 cookie 仍然會產生問題。
解決 :
Socialite::driver('google')->stateless()->user()
tl;博士
如果您需要讀取第三方服務返回的給定參數state
,您可以設置 Socialite 以避免使用stateless
方法進行這種檢查:
Socialite::driver($provider)->stateless();
我認為 Socialite 已經准備好避免這個問題。
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 傳遞數據非常有用:
參數:狀態(任何字符串)
提供在收到響應后可能對您的應用程序有用的任何狀態。 Google 授權服務器來回傳遞此參數,因此您的應用程序會收到它發送的相同值。 可能的用途包括將用戶重定向到站點中的正確資源,以及跨站點請求偽造緩解措施。
參考: https : //developers.google.com/identity/protocols/OAuth2UserAgent#overview
我只在使用 facebook 應用程序而不是瀏覽器中的 facebook 通過移動網絡登錄時遇到此錯誤。 facebook 應用程序在登錄后使用 facebook 瀏覽器而不是您當前的瀏覽器,因此不知道以前的狀態。
try {
$socialite = Socialite::driver($provider)->user();
} catch (InvalidStateException $e) {
$socialite = Socialite::driver($provider)->stateless()->user();
}
還要檢查您的storage/framework/sessions
文件夾的訪問權限。
在我的例子中,由於這個文件夾在新的 Laravel 項目中是空的,所以在最初提交到 GIT 存儲庫時它已被排除在外。 之后我在生產服務器上手動創建了它,但顯然訪問權限錯誤,因此會話驅動程序不可寫(當設置為'file'
)。
我遇到了同樣的問題,我只是清除了緩存來解決這個問題。 我剛剛運行了這個命令並再次啟動了這個過程。
php artisan cache:clear
我希望這個答案可以幫助某人。
只有當我在手機上打開我的網站並通過手機上的 Facebook 應用程序打開對話框時,才會發生同樣的情況。
我認為:發生這種情況是因為打開 facebook 應用程序以獲取來自 Facebook API 的響應使我們丟失了一些 cookie。 它變成了無國籍狀態。 然后我只是使用socialite
已經做出的選項來避免stateless
請求。
$user = Socialite::driver($provider)->stateless()->user();
它對我有用。 希望對你有幫助
如果您在 2020 年 2 月左右出現此問題,則很有可能與 2020 年 2 月初發布的 Google Chrome 80+ 版有關。我不會假裝我完全理解該問題,但簡而言之,如果沒有指定 SameSite 屬性,谷歌瀏覽器現在默認將 cookie 視為 SameSite=Lax 。
如果您的應用依賴於跨站點 cookie,則您需要在 cookie 中添加“SameSite=None; Secure”。 在 Laravel 5.5+ 中,您可以通過對會話配置進行兩項更改來實現這一點:
配置/會話.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 版本。
進一步閱讀:
得到解決方案 - 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());
}
在我的情況下,它是由User
類中$fillable
數組中缺少參數引起的。 當我添加所有缺少的參數時,它開始正常工作..
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;
}
2020 年 10 月
對我來說,我有
…\vendor\laravel\socialite\src\Two\AbstractProvider.php209
所以我轉換了我的代碼
$user = Socialite::driver('facebook')->user();
到
$user = Socialite::driver('facebook')->stateless()->user();
我不必運行任何緩存清除,雖然我確實刪除了 cookie,但我不確定您是否必須這樣做。
我解決了這個問題,只是將會話驅動程序禁用為數據庫......在嘗試修復這個問題后,文件驅動程序對我來說工作正常......
我有一個類似的問題,我有
InvalidStateException in AbstractProvider.php line 182
在函數handleProviderCallback()
當它從 Facebook 登錄handleProviderCallback()
回來時。 好像和你的問題一樣。
此外,我發現當我在沒有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 仍然會產生問題。
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,
最后我解決了:
.env
文件中的重定向URL應該與谷歌開發者帳戶中的URL相同
仔細檢查您的重定向網址。
如果您仍然需要幫助,可以使用我的代碼,它對我有用。 您只需要創建兩條路由並更新用戶表。 不要忘記使密碼可以為空,因為您不會從 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');
}
這為我解決了$request->session()->put('state',Str::random(40)); $user = Socialite::driver('github')->stateless()->user();
在callback()
方法中的控制器上
$user = $service->createOrGetUser(Socialite::driver('facebook')->user());
$user = $service->createOrGetUser(Socialite::driver('facebook')->stateless()->user());
在我的場景中,我在本地主機上運行了兩個 Laravel 應用程序,一個是實現護照,另一個是利用社交名流對護照應用程序進行身份驗證。 我忘記在.env
設置APP_NAME
,所以每個應用程序都在編寫相同的lavarel_session
cookie,所以社交應用程序無法從會話中提取狀態值,因為另一個應用程序已經踩到了 cookie。
如果您的應用程序在同一域上運行並使用您自己的提供程序,請確保在設置應用程序時在.env
設置APP_NAME
值。
我在這兩天堆積並將'driver' => env('SESSION_DRIVER', 'file')
更改為'driver' => env('SESSION_DRIVER', 'cookie')
對我有用
對我來說,解決方案是將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 列入白名單。
我遇到了同樣的問題,只是因為使用 127.0.0.1:8000/ 而不是 http://localhost:8000/
這是一個與會話相關的問題。
如果您使用的是 SSH 隧道服務,例如 ngrok.com,那么您應該使用與社交重定向 URL 完全相同的 URL,否則,您需要修改 session.php 中的域(這是一個糟糕的想法文件)。
這個問題與上面的許多解決方案無關,就像將回調 URL 從 ' http://localhost:8000/callback/twitter更改為http://127.0.0.1:8000/callback/twitter 一樣簡單在您的config/services.php
和在您的 twitter 應用程序上設置的 twitter 應用程序中。
URL 中的http://localhost是問題,替換為http://127.0.0.1
我想與您分享我的解決方案。 我轉到我的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;
}
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.