这个问题以前已经问过了,我相信我的代码是正确的,但是我得到奇怪的行为。
我需要在登录后根据一些数据库值将用户重定向到不同的路由。我认为,为了做到这一点,我只需要把我的逻辑放在app/Http/Middleware/RedirectIfAuthenticated.php
的handle
方法中。我的方法现在看起来像这样:
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';
。
高级答案:RedirectIfAuthenticated
的目的是防止已经通过身份验证的用户到达登录或注册路由/视图,因为他们已经登录。
Test:添加登录视图的书签。然后登录。关闭浏览器或窗口。打开登录书签。您将直接到用户的家或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');
}
}
您没有正确使用中间件。这段代码将在每次您登录时发送请求时触发。
要在登录后更改重定向位置,您可以在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.
}
注意:我已经用Facade替代方法(Auth::
)替换了$this->auth()
方法。只是因为我不确定AuthController是否有auth()
方法
要理解为什么您的路由逻辑从未到达,您应该查看注册了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');
但是,既然你说用户已经登录了(不是访客),你应该按照其他答案的建议移动你的代码。
只添加这个作为答案,因为它不能在注释允许的空间内澄清
解决方案在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.
}
我认为设置一个自定义中间件类来基于数据库值验证您的请求非常简单,我这样做是为了排除没有正确角色的用户。
角色在我的用户表中定义,只有具有管理员角色的用户才能访问系统。
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);
}
}
你不能更改laravel的核心文件,你需要做的就是将这段代码添加到Auth ' AuthController
protected $redirectPath = '/dashboard';