簡體   English   中英

Laravel 名媛:InvalidStateException

[英]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對問題的回答中得到了線索 - 非常感謝。

解決方案

  1. 轉到您的 www 根目錄,檢查 Laravel 文件config/session.php
  2. 檢查會話會話 Cookie 域默認配置為'domain' => null,我對'domain' => 'mysite.com'進行了更改。
  3. 'php artisan cache:clear''composer dump-autoload' ,我可以從www.mysite.commysite.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

有兩個主要的“陷阱”,現有的答案都沒有解決。

  1. 有時InvalidStateException是一個紅鯡魚,真正的根本原因是其他一些錯誤。 我花了大約 12 個小時才意識到我沒有向模型中的$fillable數組添加新字段。
  2. 除非您禁用會話狀態驗證(因為這里的其他答案似乎希望您這樣做但不是每個人都願意這樣做), $provider->user()每個請求只能調用一次,因為該函數內部調用hasInvalidState() ,然后從會話中刪除“狀態”條目。 我花了幾個小時才意識到我碰巧多次調用$provider->user() ,而我應該只調用一次並將結果保存到變量中。

我只在使用 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/04

如果您在 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:clearcomposer 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM