Laravel - 谷歌身份验证器 2FA 验证成功但无法重定向到主页

问题描述 投票:0回答:1

我想在我的 laravel 应用程序中添加 google 身份验证器 TOTP。我正在使用这个包 pragmarx/google2fa-laravel

包链接:https://github.com/antonioribeiro/google2fa-laravel

登录控制器:

`.....
 if ($userInfo["login_attempt"] < 5 || $allowLogin == true) {

                if ($this->attemptLogin($request)) {
                    if ($request->hasSession()) {
                        $request->session()->put('auth.password_confirmed_at', time());
                    }
                    $userInfo->update(array("login_attempt" => 0, "unlock_login_attempt"=> null, "status" => 1));

                    if (!$userInfo->google2fa_secret) {
                        $google2fa = app('pragmarx.google2fa');

                        $google2fa_secret = $google2fa->generateSecretKey();
                        $qrCodeUrl = $google2fa->getQRCodeInline(
                            "app name",
                            $userInfo->email,
                            $google2fa_secret
                        );

                        $userInfo->update([
                            'google2fa_secret' => $google2fa_secret
                        ]);

                        session()->put('qrCodeUrl', $qrCodeUrl); // Store $test in the session


                        return redirect()->route('admin.2fa');
                    }

                    return $this->sendLoginResponse($request);
                }
`

2FA页面(show.blade.php):

`<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2FA Verification</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>

<div class="container mt-5">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card">
                <div class="card-header">2FA Verification</div>

                <div class="card-body">
                    <form method="POST" action="">
                        @csrf
                        <div class="form-group">
                            <label for="one_time_password">Enter 6-digit OTP from your Authenticator App</label>
                            <input id="one_time_password" type="text" class="form-control @error('one_time_password') is-invalid @enderror" name="one_time_password" required autofocus>

                            @error('one_time_password')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>

                        <div class="form-group">
                            <button type="submit" class="btn btn-primary">
                                Verify OTP
                            </button>
                        </div>
                    </form>
                </div>
            </div>
             <!-- Add the QR code below the form -->
             <div class="mt-4 text-center">
              <p>Scan this QR code with your authenticator app:</p>
              {!! session('qrCodeUrl') !!}
          </div>
        </div>
    </div>
</div>

</body>
</html>

`

双因素控制器:


class TwoFactorController extends Controller
{
    public function show()
    {
        return view('auth.google2fa.show'); // Use the appropriate view for your 2FA verification page
    }

    public function verify(Request $request)
    {
        $validated = $request->validate([
            'one_time_password' => 'required',
        ]);

        $user = Auth::user();
        $google2fa = app('pragmarx.google2fa');
        $valid = $google2fa->verifyKey($user->google2fa_secret, $request->input('one_time_password'));
        // Verify the 2FA code using the package's functionality
        if ($valid) {
            // 2FA code is valid, proceed with login
            return redirect()->route('admin.dashboard');
        } else {
            // Invalid 2FA code, redirect back with an error message
            return redirect()->route('2fa')->withErrors(['one_time_password' => 'Invalid OTP code']);
        }
    }
}

我的web.php:


Route::group([
    'middleware' => ['auth'],
], function () {
    Route::get('/2fa', [TwoFactorController::class, 'show'])->name('2fa-page');
    Route::post('/2fa', [TwoFactorController::class, 'verify'])->name('verify-2fa');
});

Route::group([
    'middleware' => ['auth', '2fa'],
    'as'         => 'admin.',
], function () {
    Route::get('/', [DashboardController::class, 'index'])
        ->name('dashboard');
....

用户成功登录(电子邮件和密码)后,他们将被重定向到 2FA 页面,可以在其中扫描 QR 码并在表单上输入 OTP。之后,一旦 OTP 验证成功,它们将被重定向到仪表板主页。我的流程似乎一直有效,直到验证成功。当 OTP 成功时,它无法重定向到主页,而是不断重定向回 2FA 页面。

我不确定问题是什么,因为我已经查看了该包的文档,但没有解决我的问题。我的猜测是它仍然没有“通过”2FA 中间件,因此重定向回 2FA 页面。

我尝试删除路由中的 2FA 中间件,它会起作用,但这违背了中间件的目的,因为任何人都可以通过将 url 更改为另一个页面来轻松绕过 2FA 挑战。

但是接下来会发生什么呢?这个值保存在哪里?我们如何检查 2fa 是否已通过验证? 中间件在每个点都会失败,所以我宁愿自己制作,但如果用户经过验证,我们如何知道在哪里拉取?

似乎文档就结束了,不知道下一步该做什么。

任何帮助/见解将不胜感激。

laravel two-factor-authentication google-2fa
1个回答
0
投票

在 Laravel 中的典型 2FA 流程中,成功验证 2FA 后,您可能需要在用户会话中设置一个标志来指示 2FA 检查已通过。然后,在您的中间件中,您将检查此标志。在注销时取消设置标志也是一个好主意。

简化的方法是在您的

TwoFactorController
verify()
方法中成功验证后首先设置一个标志:

if ($valid) {
    // 2FA code is valid, proceed with login
    $request->session()->put('2fa_verified', true);
    return redirect()->route('admin.dashboard');
}

然后,您可以调整自定义 2FA 中间件(

auth
2fa
)以首先检查会话变量
'2fa_verified'
是否设置为
true
。伪示例:

public function handle($request, Closure $next)
{
    if ($request->session()->get('2fa_verified') === true) {
        return $next($request);
    }

    return redirect()->route('2fa-page');
}

您可以在 Christopher Thomas 的“2FA in Laravel with Google Authenticator – Get Secure!”中看到更详细的示例,尽管该文章写于 2016 年。也许更新的功能可能会简化此工作流程。

© www.soinside.com 2019 - 2024. All rights reserved.