在 Laravel 的内置身份验证中重定向是否经过身份验证的逻辑?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33341150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 12:34:34  来源:igfitidea点击:

Redirect if authenticated logic in Laravel's built-in auth?

phplaravelauthenticationlaravel-5.1

提问by Mike

This question has been asked before, and I believe my code to be correct, but I am getting strange behaviour.

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

I need to redirect the user to different routes after login depending on some database values. I thought that in order to do this I simply had to place my logic in the handlemethod of app/Http/Middleware/RedirectIfAuthenticated.php. My method currently looks like so:

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

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

This does not work, and upon login the user is redirected to /home. I have tried placing dd($this->auth->user())inside the $this->auth->check()condition, but it never gets run. If I place it outside of that check then it's run on every request. It looks like $this->auth->check()is never run.

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

My question: If not here, where should this logic go?

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

I have removed protected $redirectTo = '/account';from the AuthController.phpcontroller too.

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

采纳答案by Mark Walet

You are not using the middleware correctly. This piece of code will fire everytime you send a request when you are logged in.

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

To change the redirect location after login you can override the redirectPath()method in your AuthController. (You can find the original method in vendor/laravel/framework/src/Illuminate/Foundation/Auth/RedirectsUsers.php)

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

This would look something like this:

这看起来像这样:

...

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.

}

Note: I've replaced the $this->auth()method with the Facade alternative (Auth::). Just because I am not sure if the AuthController has an auth()method.

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

回答by mangonights

High level answer: the purpose of RedirectIfAuthenticatedis to keep an already authenticated user from reaching the login or registration routes/views since they're already logged in.

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

Test: bookmark the login view. Then login. Close the browser or window. Open the login bookmark. You'll go straight to user's home or where ever specified in RedirectIfAuthenticated.

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

For purposes of the LoginController, create a redirecTo()method, which is what the redirectPath()method looks for to see if you have customized the redirect.

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

回答by Dmitry

Solution is in Mark Walet's answer, but need little correction. Return should be a string:

解决方案在 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.

}

回答by 0x1ad2

I think it's so easy as setting up a custom Middleware class to validate your requests based on the database values, I do this for excluding users without the correct role.

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

The role is defined in my user table and only users with the administrator role are allowed to access the system.

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

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

    }
}

回答by Amir Tahani

u cant change the core files of laravel all u need to do is adding this code to Auth\AuthController

你不能改变 Laravel 的核心文件,你需要做的就是将此代码添加到 Auth\AuthController

protected $redirectPath = '/dashboard';

回答by Jannie Theunissen

To understand why your routing logic is never reached, you should look in app/Http/Kernel.phpwhere the RedirectIfAuthenticated middleware is registered:

要了解为什么永远不会到达您的路由逻辑,您应该查看app/Http/Kernel.phpRedirectIfAuthenticated 中间件的注册位置:

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

This means if a user navigates to a route that is not protected by the guestroute middleware, the request never passes through the RedirectIfAuthenticated class and so misses your logic completely.

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

You can add guest middleware to your registration routes in your routes file to force the routing to pass through your code like this:

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

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

But, since you say the user is already logged in (not a guest) you should instead move your code as suggested by the other answers.

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

Only adding this as an answer, because it couldn't be clarified in the space allowed by a comment.

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