【问题标题】:Apply Laravel 5.7 MustVerifyEmail on Multiple Authentication System在多重身份验证系统上应用 Laravel 5.7 MustVerifyEmail
【发布时间】:2019-04-10 17:23:47
【问题描述】:

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

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

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

我应该错过了什么。

这是 GitHub 上的project file

提前感谢您的帮助。

【问题讨论】:

    标签: laravel email-verification


    【解决方案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);
        }
    }
    

    这解决了我的问题。

    【讨论】:

      【解决方案2】:

      M.Islam 的回答很好,但请确保覆盖对 EnsureEmailIsVerified 的更改,而不是直接修改源文件。否则,每当您进行 $composer 更新或推送到生产环境时,您的更改可能会丢失。

      【讨论】:

        【解决方案3】:

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

        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');
        }
        

        因此,您可以手动将这些添加到您的 web.php 路由文件中,而不是使用 Auth::routes(),然后给它们命名路由。

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

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

        您可以按照此处的示例,在验证邮件过程和忘记密码密码的过程中覆盖它。

        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 默认为 User 但如果您使用具有多个租户身份验证的自定义守卫,您可以将其应用于您的相关模型。

        然后你的模型上会有以下内容

        /**
         * 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 文件...此文件不是供应商文件的一部分,虽然作为基本安装的一部分提供给您,但它留给您更改更新和更改...我们所做的更改只是为了容纳警卫,而不是允许多租户或不在应用程序中的广泛更改。

        对于任何人,我希望这会有所帮助,并且我在旅途中学习了这一点,并希望在我忘记时参考这一点,并希望它可以帮助任何走类似道路的人。

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 2019-05-14
            • 1970-01-01
            • 2023-03-14
            • 1970-01-01
            • 2019-06-14
            • 2018-07-21
            • 2018-10-17
            • 2015-07-01
            • 2019-04-30
            相关资源
            最近更新 更多