在多重身份验证系统上应用Laravel 5.7 MustVerifyEmail

时间:2018-11-07 09:37:19

标签: laravel email-verification

我正在尝试在多个身份验证系统上应用Laravel-5.7 MustVerifyEmail。到目前为止,我所做的如下:

  1. 为“审计师”后卫创建了验证路径。
  2. 用新的视图覆盖Verification控制器中的show方法。
  3. 在审核员模型中实施了新通知。
  4. 创建,注册并应用了一个名为“ auditor.verified”的新中间件。

此过程完成后,我发现它正在向电子邮件发送通知并显示“验证”页面,但是当我单击邮件中的“验证电子邮件地址”按钮时,它将使用时间戳更新数据库,但不会花费我时间到重定向页面。相反,我在浏览器中收到“页面无法正常工作”的消息。

我应该错过一些东西。

这是GitHub上的project file

预先感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

最后,经过四天的研究,我能够解决问题。

我如下更改了“ EnsureEmailIsVerified”中间件:

<?php

namespace Illuminate\Auth\Middleware;

use Closure;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Support\Facades\Auth;

class EnsureEmailIsVerified
{

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
 */
public function handle($request, Closure $next, $guard = null)
{

    $guards = array_keys(config('auth.guards'));

    foreach($guards as $guard) {

        if ($guard == 'admin') {

            if (Auth::guard($guard)->check()) {

                if (! Auth::guard($guard)->user() ||
                    (Auth::guard($guard)->user() instanceof MustVerifyEmail &&
                    ! Auth::guard($guard)->user()->hasVerifiedEmail())) {
                    return $request->expectsJson()
                            ? abort(403, 'Your email address is not verified.')
                            : Redirect::route('admin.verification.notice');
                }  

            }

        }

        elseif ($guard == 'auditor') {

            if (Auth::guard($guard)->check()) {

                if (! Auth::guard($guard)->user() ||
                    (Auth::guard($guard)->user() instanceof MustVerifyEmail &&
                    ! Auth::guard($guard)->user()->hasVerifiedEmail())) {
                    return $request->expectsJson()
                            ? abort(403, 'Your email address is not verified.')
                            : Redirect::route('auditor.verification.notice');
                }  

            }

        }

        elseif ($guard == 'web') {

            if (Auth::guard($guard)->check()) {

                if (! Auth::guard($guard)->user() ||
                    (Auth::guard($guard)->user() instanceof MustVerifyEmail &&
                    ! Auth::guard($guard)->user()->hasVerifiedEmail())) {
                    return $request->expectsJson()
                            ? abort(403, 'Your email address is not verified.')
                            : Redirect::route('verification.notice');
                    }  

                }
            }

        }

        return $next($request);
    }
}

这解决了我的问题。

答案 1 :(得分:1)

所以有一个类似的问题...

StackOverflow::Route [user.verification.notice] not defined / Override EnsureEmailIsVerified?

使用多个防护罩时,您只能在

中进行一些防护罩重定向
App\Middleware\Authenticate.php

protected function redirectTo($request)
{
    if (! $request->expectsJson()) {
        if (Arr::first($this->guards) === 'admin') {
            return route('admin.login');
        }

        if (Arr::first($this->guards) === 'user') {
            return route('user.login');
        }

        return route('login');
    }
}

您只需将所有验证路由添加到您的web.php文件并更改命名的路由。

所有身份验证路由都可以在

中找到
Illuminate\Routing\Router.php
\
/**
 * Register the typical authentication routes for an application.
 *
 * @param  array  $options
 * @return void
 */
public function auth(array $options = [])
{
    // Authentication Routes...
    $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
    $this->post('login', 'Auth\LoginController@login');
    $this->post('logout', 'Auth\LoginController@logout')->name('logout');

    // Registration Routes...
    if ($options['register'] ?? true) {
        $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
        $this->post('register', 'Auth\RegisterController@register');
    }

    // Password Reset Routes...
    if ($options['reset'] ?? true) {
        $this->resetPassword();
    }

    // Email Verification Routes...
    if ($options['verify'] ?? false) {
        $this->emailVerification();
    }
}

/**
 * Register the typical reset password routes for an application.
 *
 * @return void
 */
public function resetPassword()
{
    $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
    $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
    $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
    $this->post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update');
}

/**
 * Register the typical email verification routes for an application.
 *
 * @return void
 */
public function emailVerification()
{
    $this->get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
    $this->get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify');
    $this->post('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');
}

因此,除了使用Auth :: routes()之外,您还可以将其手动添加到web.php路由文件中,并仅为其命名路由。

注意:更改命名路由后,您需要在视图中正确引用它们。

它首先要抱怨的是通知邮件,它引用了默认的命名路由...

您可以按照此处的示例在验证邮件过程和忘记密码密码这两个方面进行操作。

Forgot Password Custom Named Route and Email

要实现此目的,您将必须通过创建两个自定义的自定义通知来覆盖这两个默认通知,以覆盖电子邮件通知。

您将模拟文件中找到的laravel默认结构

Illuminate\Auth\Notifications\VerifyEmail.php
Illuminate\Auth\Notifications\ResetPassword

一旦创建了2个通知邮件。

例如

php artisan make:notification MailEmailVerificationNotification

在App \ Notifications \ MailEmailVerificationNotification中创建一个文件,该文件可以有效地复制Illuminate \ Auth \ Notifications \ VerifyEmail.php文件

您将把方法添加到模型中。 Laravel的默认值为“用户”,但是如果您使用具有多个租户身份验证的自定义防护,则可以将其应用于相关模型。

您将在模型上包含以下内容

/**
 * Send the password reset notification.
 * App\Notifications\MailResetPasswordNotification.php
 *
 * @param  string  $token
 * @return void
 */
public function sendEmailVerificationNotification()
{
    $this->notify(new MailEmailVerificationNotification());
}

走这条路线会更好,因为您可以覆盖Laravel的默认逻辑,但是您不编辑任何Laravel特定的文件,这意味着它们在更新Laravel时不会被覆盖,并且仅在设计更改(例如最近的移动)时才会受到影响将Laravel UI提取到其自己的程序包中,该程序在密码重置路径上做了些微改动。

您可能会注意到我们更改了App \ Middleware \ Authenticate文件...此文件不属于供应商文件,当作为基础文件的一部分提供给您时,请安装其左侧以供您更改更新和更改...我们所做的更改仅是为了容纳警卫人员,而不是为了允许多租户而在应用程序中不允许进行的大量更改。

对于任何人,我希望这对我有帮助,我继续学习它,并希望在我忘记并希望它对任何人走相似的道路时提供参考。

答案 2 :(得分:0)

M.Islam的答案很不错,但是请确保覆盖对确保电子邮件EsVerified的更改,而不是直接修改源文件。否则,每当您进行$ composer更新或投入生产时,所做的更改都将丢失。

答案 3 :(得分:0)

我在__construct中修改了中间件参数,并且电子邮件验证对我有用。我正在使用laravel6。尽管问题很旧,但仍在此处发布答案

public function __construct()
{
    $this->middleware('auth:<your_guard>');
    $this->middleware('signed')->only('verify');
    $this->middleware('throttle:6,1')->only('verify', 'resend');
}