Google2FA 是 Google 雙重認證模組的 PHP 實現,支援 RFC 4226 中指定的基於 HMAC 的一次性密碼 (HOTP) 演算法和 RFC 6238 中指定的基於時間的一次性密碼 (TOTP) 演算法。
PHP | 谷歌2FA |
---|---|
5.4 | 7.x 長期支持 |
5.5 | 7.x 長期支持 |
5.6 | 7.x 長期支持 |
7.1 | 8.x |
7.2 | 8.x |
7.3 | 8.x |
7.4 | 8.x |
8.0(β) | 8.x |
這個包是不可知的,但有一個 Laravel 橋。
此軟體包不會產生 2FA 的 QRCodes。
如果您正在尋找 Google 雙重認證,但還需要為其生成 QRCode,您可以使用 Google2FA QRCode 包,該包集成了此包並使用 BaconQRCode 庫生成 QRCode,或者檢查有關如何自行生成 QRCode 的選項在文檔中。
請檢查 Google2FA Package Playground。
這是一個演示應用程序,展示如何使用 Google2FA:google2fa-example。
您可以使用 Google Authenticator 應用程式掃描此(舊)演示頁面上的二維碼,並(幾乎)即時查看程式碼變更。
使用 Composer 來安裝它:
composer require pragmarx/google2fa
要產生內聯 QRCodes,您需要安裝 QR 碼產生器,例如 BaconQrCode:
composer require bacon/bacon-qr-code
use PragmaRX Google2FA Google2FA ;
$ google2fa = new Google2FA ();
return $ google2fa -> generateSecretKey ();
為您的用戶產生密鑰並保存:
$ user -> google2fa_secret = $ google2fa -> generateSecretKey ();
建立 QRCode 的更安全方法是自己建立或使用庫。首先,您必須安裝 QR 碼產生器,例如 BaconQrCode,如上所述,然後您只需使用以下命令產生 QR 碼 url:
$ qrCodeUrl = $ google2fa -> getQRCodeUrl (
$ companyName ,
$ companyEmail ,
$ secretKey
);
獲得 QR 碼 URL 後,您可以將其提供給您首選的 QR 碼產生器。
// Use your own QR Code generator to generate a data URL:
$ google2fa_url = custom_generate_qrcode_url ( $ qrCodeUrl );
/// and in your view:
<img src="{{ $ google2fa_url }}" alt="">
要驗證,您只需:
$ secret = $ request -> input ( ' secret ' );
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret );
這個包建議使用Bacon/QRCode,因為它被認為是一個很好的QR 碼包,但您可以將它與任何其他包一起使用,例如Google2FA QRCode、Simple QrCode 或Endroid QR Code,它們都使用Bacon/QRCode來產生二維碼。
通常您需要一個 2FA URL,因此您只需使用 URL 產生器:
$ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )
取得要內聯使用的 QRCode:
$ google2fa = ( new PragmaRX Google2FAQRCode Google2FA ());
$ inlineUrl = $ google2fa -> getQRCodeInline (
' Company Name ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
並在您的模板中使用:
<img src="{{ $ inlineUrl }}">
<div class="visible-print text-center">
{!! QrCode :: size ( 100 )-> generate ( $ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )); !!}
<p> Scan me to return to the original page.</p>
</div>
產生數據URL
$ qrCode = new Endroid QrCode QrCode ( $ value );
$ qrCode -> setSize ( 100 );
$ google2fa_url = $ qrCode -> writeDataUri ();
而在你看來
<div class="visible-print text-center">
{!! $ google2fa_url !!}
<p> Scan me to return to the original page.</p>
</div>
<?php
use PragmaRX Google2FA Google2FA ;
use BaconQrCode Renderer ImageRenderer ;
use BaconQrCode Renderer Image ImagickImageBackEnd ;
use BaconQrCode Renderer RendererStyle RendererStyle ;
use BaconQrCode Writer ;
$ google2fa = app ( Google2FA ::class);
$ g2faUrl = $ google2fa -> getQRCodeUrl (
' pragmarx ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
$ writer = new Writer (
new ImageRenderer (
new RendererStyle ( 400 ),
new ImagickImageBackEnd ()
)
);
$ qrcode_image = base64_encode ( $ writer -> writeString ( $ g2faUrl ));
並將其顯示為圖像:
<img src="data:image/png;base64, <?php echo $ qrcode_image; ?> "/>
為了符合 RFC6238,該軟體包支援 SHA1、SHA256 和 SHA512。它預設為 SHA1,因此要使用不同的演算法,您只需使用方法setAlgorithm()
:
use PragmaRX Google2FA Support Constants ;
$ google2fa -> setAlgorithm ( Constants :: SHA512 );
保持伺服器時間與某些 NTP 伺服器同步非常重要,在 Ubuntu 上,您可以將其新增至 crontab :
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
為了避免時鐘稍微不同步的問題,我們不僅檢查當前密鑰,還考慮過去和未來的$window
鍵。您可以將$window
作為可選的第三個參數傳遞給verifyKey
,它預設為1
。如果每 30 秒產生一個新金鑰,則在預設設定下,將考慮前一個、目前和下一個 30 秒間隔的金鑰。對於時脈正確同步的使用者來說,金鑰的有效期看起來是 60 秒而不是 30 秒,因為即使金鑰已經過期(比方說 29 秒),系統也會接受它。
$ secret = $ request -> input ( ' secret ' );
$ window = 8 ; // 8 keys (respectively 4 minutes) past and future
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret , $ window );
將$window
參數設為0
也可能表示系統不會接受使用者在生成器中看到的有效金鑰,因為使用者通常需要一些時間才能將金鑰輸入到特定表單欄位。
攻擊者可能能夠看到使用者輸入其憑證和一次性金鑰。如果沒有進一步的預防措施,金鑰將保持有效,直到它不再處於伺服器時間視窗內。為了防止使用已經使用過的一次性金鑰,您可以使用verifyKeyNewer
函數。
$ secret = $ request -> input ( ' secret ' );
$ timestamp = $ google2fa -> verifyKeyNewer ( $ user -> google2fa_secret , $ secret , $ user -> google2fa_ts );
if ( $ timestamp !== false ) {
$ user -> update ([ ' google2fa_ts ' => $ timestamp ]);
// successful
} else {
// failed
}
請注意, $timestamp
要么為false
(如果密鑰無效或之前已使用過),要么為提供的密鑰的 unix 時間戳除以 30 秒的密鑰重新生成週期。
雖然 16 個位元組(128 位元)隨機字串的衝突機率非常低,但您可以透過以下方式對其進行強化:
$ secretKey = $ google2fa -> generateSecretKey ( 32 ); // defaults to 16 bytes
您可以為您的秘密金鑰加上前綴,但您必須了解,由於您的秘密金鑰的長度必須為 2 的冪,因此您的前綴必須具有互補的大小。因此,如果您的金鑰是 16 位元組長,如果您添加前綴,它也必須是 16 位元組長,但由於您的前綴將轉換為基數 32,因此前綴的最大長度為 10 位元組。因此,這些是您可以在前綴中使用的大小:
1, 2, 5, 10, 20, 40, 80...
它可以像這樣使用:
$ prefix = strpad ( $ userId , 10 , ' X ' );
$ secretKey = $ google2fa -> generateSecretKey ( 16 , $ prefix );
Window 屬性定義 OTP 將工作多長時間,或將持續多少週期。按鍵有 30 秒的週期,將視窗設為 0 將使按鍵持續 30 秒,將其設為 2 將使按鍵持續 120 秒。這是設定視窗的方法:
$ secretKey = $ google2fa -> setWindow ( 4 );
但您也可以在檢查按鍵的同時設定視窗。如果您需要在金鑰驗證期間將視窗設為 4,請執行以下操作:
$ isValid = $ google2fa -> verifyKey ( $ seed , $ key , 4 );
您可以更改金鑰重新產生間隔,預設為 30 秒,但請記住,這是大多數身份驗證應用程式(例如 Google Authenticator)的預設值,這基本上會使您的應用程式與它們不同步。
$ google2fa -> setKeyRegeneration ( 40 );
為了與 Google Authenticator 相容,您的(轉換為基數 32)金鑰長度必須至少為 8 個字符,並且是 2 的冪:8、16、32、64...
因此,為了防止錯誤,您可以在生成它時執行以下操作:
$ secretKey = ' 123456789 ' ;
$ secretKey = str_pad ( $ secretKey , pow ( 2 , ceil ( log ( strlen ( $ secretKey ), 2 ))), ' X ' );
並且它會生成
123456789XXXXXXX
預設情況下,此套件將強制相容性,但是,如果 Google Authenticator 不是目標,您可以透過執行以下操作來停用它
$ google2fa -> setEnforceGoogleAuthenticatorCompatibility ( false );
要使用兩因素身份驗證,您的用戶必須安裝 Google Authenticator 相容應用程序,這些是目前可用的一些應用程式:
用於 QR 產生器的 Google API 已關閉。該軟體包 5.0.0 之前的所有版本均已棄用。請升級並檢查有關 QRCode 產生的文件。
套件測試是用 PHPUnit 寫的。有一些 Composer 腳本可以幫助您執行測試和分析:
PHP 單位:
composer test
PHPStan分析:
composer analyse
Google2FA 根據 MIT 許可證獲得許可 - 有關詳細信息,請參閱許可證文件。
拉取請求和問題非常受歡迎。
沒有任何。