将登录用户重定向到 Laravel Jetstream / Fortify 中的个人资料页面以启用 2-factor?

问题描述

如果用户没有为他们的个人资料启用 2 因素身份验证,我一直在寻找一种将登录用户重定向到他们的个人资料页面方法(理想情况下希望对所有路线都这样做)。 我使用的是 Laravel 8、Fortify 和 Jetstream。

如果 users 表中的 two_factor_secrettwo_factor_recovery_codes相关用户为 NULL,则 2-factor 似乎未启用。如果这些 DB 列不是 NULL,它至少是启用的。一个可能检查的地方如下所示:

/app/Providers/FortifyServiceProvider.PHP

认设置:

$user = User::where('email',$request->email)->first();

验证登录信息,如果他们通过身份验证,我会做一些内务处理。

认情况下,脚本末尾有一个 return $user。

我可以检查脚本中的 $user->two_factor_secret 是否为非空,所以如果有可能以某种方式动态更改可能有效的路线,至少就初始登录而言,但我更愿意检查应用程序中每条路线的 2 因素启用状态(只是状态,而不是代码)。我不太清楚该怎么做?在某个地方的 ServiceProvider 中或在 routes/web.PHP 等中。我想有可能以某种方式将我的所有路由包装在一个组中,并且他们在处理之前以某种方式检查 routes/web.PHP 中的两步状态请求的路线?

任何帮助将不胜感激。真的有两种选择。如果他们没有激活两步(即填充有数据的 DB 字段),则登录时只是警告和重定向到个人资料页面(/用户/个人资料),然后更全局的选项总是重定向到任何人的个人资料页面如果他们没有启用 2 步(这将阻止导航到个人资料页面以外的任何其他页面)。

谢谢。

解决方法

我建议创建一个自定义 middleware,它可以应用于一组路由,这将确定经过身份验证的用户是否已启用 2FA

namespace App\Http\Middleware;

use Closure;

class HasTwoFactorAuthEnabled
{
    public function handle($request,Closure $next)
    {
        if (is_null(Auth::user()->two_factor_secret)) {
            return redirect(route('user.profile.2fa'));
        }

        return $next($request);
    }
}

在上面,如果经过身份验证的用户的 two_factor_secret 的值为 null,我们假设它没有启用,因此重定向用户。否则请求继续到下一个中​​间件。

由于您可能不想对所有 HTTP 请求甚至所有 web 请求执行此检查,因此您需要在 $routeMiddleware 数组中注册中间件app/Http/Kernel.php

protected $routeMiddleware = [
    'has2FaEnabled' => \App\Http\Middleware\HasTwoFactorAuthEnabled::class,];

然后您可以将中间件应用于单个路由或一组路由。例如;

Route::group(['middleware' => ['has2FaEnabled']],function () {
    Route::get('/profile',ProfileController::class);
});

现在,如果用户没有启用 2FA,您是否想要/应该重定向他们实际上取决于您的用例和应用程序类型。如果安全性对您很重要,或者您的应用程序中管理的数据是敏感的,那么强制执行 2FA 可能是一个好主意。否则,如果您只是提供 2FA 功能以提高安全性,我可能会建议避免强制用户启用它,而只是建议用户启用它或在​​未启用时阻止访问某些“敏感”功能。

,

我不得不稍微调整中间件才能让它在我的设置中工作:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Auth\Middleware\Authenticate as Middleware;

class HasTwoFactorAuthEnabled extends Middleware
{
    public function handle($request,Closure $next,...$guards)
    {
        if (is_null(Auth::user()->two_factor_secret)) {
            session(['modal_message' => 'You Need to Enable 2-Factor Auth']);
            return redirect(route('profile.show'));
        }

        return $next($request);
    }
}

虽然这似乎有效,但在 web.php 中,就像测试一样:

Route::group(['middleware' => ['has2FaEnabled']],function () {
    Route::get('/',function () {
        return view('welcome');
    })->name('welcome');
});

在我的 layouts/app.blade.php 中有一个东西可以处理模态消息。我实际上也开始测试 Spatie 的 CSP 包的使用,这就是为什么那里有一个 nonce,尽管我希望最终避免使用内联脚本。

<!-- The Modal -->
<div class="modal fade hide" id="myModal" data-keyboard="true" data-backdrop="true" tabindex='-1'>

    <div class="modal-dialog">
    <div class="modal-content">

      <!-- Modal Header -->
      <div class="modal-header">
        <h4 class="modal-title"></h4>
        <button type="button" class="close" data-dismiss="modal">&times;</button>
      </div>

      <!-- Modal body -->
      <div class="modal-body"></div>

      <!-- Modal footer -->
      <div class="modal-footer">
        <button type="button" class="uibuttonsmallred" data-dismiss="modal">Close</button>
      </div>

    </div>
    </div>
</div>
<?php
$modal_message = session('modal_message',false);
if ($modal_message !== false) {
?>
    <script nonce= "{{ csp_nonce() }}">
    $(window).on('load',function() {
        $('#myModal .modal-body').html('<?php echo $modal_message ?>');
        $('#myModal').modal('show');
    });
    </script>
<?php
}
?>

这会重定向到个人资料页面,即我系统上的 profile.show。剩下的我应该可以处理。谢谢。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...