【问题标题】:Redirect if authenticated logic in Laravel's built-in auth?如果 Laravel 的内置身份验证中经过身份验证的逻辑,则重定向?
【发布时间】:2016-01-25 06:44:33
【问题描述】:

以前有人问过这个问题,我相信我的代码是正确的,但我的行为很奇怪。

我需要在登录后根据某些数据库值将用户重定向到不同的路由。我认为为了做到这一点,我只需将我的逻辑放在app/Http/Middleware/RedirectIfAuthenticated.phphandle 方法中。我的方法目前看起来像这样:

public function handle($request, Closure $next)
{

    if ($this->auth->check()) {
        if($this->auth->user()->sign_up_complete == 1){
            return redirect('/');
        } else {
            if($this->auth->user()->step_one_complete == 0){
                return redirect('/register/step-1');
            } elseif($this->auth->user()->step_two_complete == 0){
                return redirect('/register/step-2');
            } else {
                return redirect('/');
            }
        }
    }

    return $next($request);
}

这不起作用,并且在登录时用户被重定向到/home。我尝试将dd($this->auth->user()) 放在$this->auth->check() 条件内,但它永远不会运行。如果我将它放在该检查之外,那么它会在每个请求上运行。看起来$this->auth->check() 从未运行过。

我的问题:如果不在这里,这个逻辑应该去哪里?

我也从AuthController.php 控制器中删除了protected $redirectTo = '/account';

【问题讨论】:

  • check() 函数在哪里
  • RedirectIfAuthenticated 似乎是 guest 中间件。同样在Illuminate\Foundation\Auth\RedirectUsers中如果没有设置$redirectTo,会被重定向到/home。但在这种情况下没关系。您是否尝试过 Authenticate 中间件?在$this->auth->guest() 检查之后移动你的逻辑,你写了什么。如果需要对用户进行身份验证,此中间件将每次运行。因此,如果未通过身份验证,基本检查将重定向它们。如果是,它将继续您的检查。
  • @Iamzozo 我不确定我是否遵循。这似乎完全是为了别的东西?
  • 看来。如果我使用guest 中间件,它运行RedirectIfAuthenticated。但是auth 中间件不是运行RedirectIfAuthenticated,而是运行Authenticate。因为您要在登录后检查用户,如果他完成了所有步骤,所有带有auth 的受保护页面将运行Authenticate 中间件,所以运行您的检查。 guest 如果您想将用户从不需要的页面重定向,则使用中间件。例如,如果用户已登录,则您不希望显示登录表单。在这里你使用guest 中间件,如果他已经登录,它将调用RedirectIfAuthenticated 并重定向到主页。
  • @mikemike 您是否在控制器中为middleware 编写代码?

标签: php laravel authentication laravel-5.1


【解决方案1】:

高级答案:RedirectIfAuthenticated 的目的是防止已通过身份验证的用户访问登录或注册路由/视图,因为他们已经登录。

测试:为登录视图添加书签。然后登录。关闭浏览器或窗口。打开登录书签。您将直接前往用户家中或RedirectIfAuthenticated 中指定的地方。

为了 LoginController 的目的,创建一个 redirecTo() 方法,这是 redirectPath() 方法查找的内容,以查看您是否自定义了重定向。

// example
public function redirectTo()
{
    switch (auth()->user()->role) {
        case 'foo':
            return route('foo.home');

        case 'bar':
            return route('bar.home');

        default:
            auth()->logout();
            return route('web.welcome');
    }
}

【讨论】:

    【解决方案2】:

    您没有正确使用中间件。每次您在登录时发送请求时都会触发这段代码。

    要在登录后更改重定向位置,您可以覆盖 AuthController 中的 redirectPath() 方法。 (可以在vendor/laravel/framework/src/Illuminate/Foundation/Auth/RedirectsUsers.php找到原方法)

    这看起来像这样:

    ...
    
    public class AuthController extends Controller {
    
        ...
    
        public function redirectPath()
        {
            if(Auth::user()->sign_up_complete == 1) {
                return '/';
            } else {
                if(Auth::user()->step_one_complete == 0) {
                    return '/register/step-1';
                } elseif(Auth::user()->step_two_complete == 0) {
                    return '/register/step-2';
                } else {
                    return '/';
                }
            }
        }
    
    
        // The rest of the class implementation.
    
    }
    

    注意:我已将 $this->auth() 方法替换为 Facade 替代方法 (Auth::)。只是因为我不确定 AuthController 是否有 auth() 方法。

    【讨论】:

      【解决方案3】:

      要了解为什么您的路由逻辑永远无法到达,您应该查看注册了 RedirectIfAuthenticated 中间件的app/Http/Kernel.php

      protected $routeMiddleware = [
          ...
          'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
          ...
      ];
      

      这意味着如果用户导航到不受 guest 路由中间件保护的路由,则请求永远不会通过 RedirectIfAuthenticated 类,因此完全错过了您的逻辑。

      您可以在您的路由文件中将访客中间件添加到您的注册路由中,以强制路由通过您的代码,如下所示:

      Route::get('/register/step-1', '<YOUR CONTROLLER METHOD>')->middleware('guest');
      

      但是,由于您说用户已经登录(不是访客),您应该按照其他答案的建议移动您的代码。

      仅将其添加为答案,因为无法在评论允许的空间中澄清它。

      【讨论】:

        【解决方案4】:

        解决方案在 Mark Walet 的回答中,但几乎不需要更正。返回应该是一个字符串:

        public class AuthController extends Controller {
        
            ...
        
            public function redirectPath()
            {
                if(Auth::user()->sign_up_complete == 1) {
                    return '/';
                } else {
                    if(Auth::user()->step_one_complete == 0) {
                        return '/register/step-1';
                    } elseif(Auth::user()->step_two_complete == 0) {
                        return '/register/step-2';
                    } else {
                        return '/';
                    }
                }
            }
        
        
            // The rest of the class implementation.
        
        }
        

        【讨论】:

        • 这应该是您在我的解决方案的评论中所说的。然后我收到通知并立即更新。
        • 哦..好的,对不起。下次会这样做
        【解决方案5】:

        你不能改变 laravel 的核心文件,你需要做的就是将这段代码添加到 认证\认证控制器

        protected $redirectPath = '/dashboard';
        

        【讨论】:

          【解决方案6】:

          我认为设置自定义中间件类以根据数据库值验证您的请求非常简单,我这样做是为了排除没有正确角色的用户。

          角色在我的用户表中定义,只有具有管理员角色的用户才能访问系统。

          namespace App\Http\Middleware;
          
          use Closure;
          use Illuminate\Support\MessageBag;
          
          class RolesMiddleware
          {
              /**
               * Handle an incoming request.
               *
               * @param  \Illuminate\Http\Request  $request
               * @param  \Closure  $next
               * @return mixed
               */
              public function handle($request, Closure $next)
              {
                  // If a user is authenticated
                  if(\Auth::user() != null)
                  {
                      // If the user doesn't have the correct role
                      if(\Auth::user()->role != 'administrator')
                      {
                          // logout the user
                          \Auth::logout();
          
                          // create a new MessageBag
                          $messageBag = new MessageBag;
          
                          // add a message
                          $messageBag->add('not_allowed', 'You are not allowed to login, because you do not have the right role!');
          
                          // redirect back to the previous page with errors
                          return \Redirect::to('login')->withErrors($messageBag);
                      }
                  }
          
                  return $next($request);
          
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2018-05-11
            • 1970-01-01
            • 2018-02-22
            • 2019-04-25
            • 1970-01-01
            • 2016-12-30
            • 2022-01-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多