Laravel 登录之后,跳转回登录前的页面

文章目录

    场景

    我自定义了一套 laravel 的登录逻辑,使用手机号加验证码登录,没有使用 laravel 内置的登录逻辑。

    实现方法

    先列一下解决方法,然后再一一说明。

    例如,如果购物车页面需要登录之后才能访问,并且点击购物车,弹出登录页面,完成登录之后,需要跳回到购物车页面。

    首先需要在 route 上加上权限控制。

    Route/web.php

    Route::get('cart', [
        'uses' => 'CartController@cart_index',     // 购物车页面
    ])->middleware('auth');
    

    在 web.php 内的 route 不需要再单独加上一层 web group。

    同时给 login 路由设置一个 name,为 login。否则 auth middleware 会报错:local.ERROR: Route [login] not defined

    Route::get('/login', [
        'uses' => 'LoginController@index',
        'as' => 'login',
    ]);
    

    在 LoginController 中,Login 验证完成之后,跳转逻辑修改为

    return redirect()->intended();
    

    好了,这样就可以了。

    下面记录一些细节的说明。

    session

    https://laravel.com/docs/5.5/session

    Since HTTP driven applications are stateless, sessions provide a way to store information about the user across multiple requests.

    两种调用方法:

    第一种,通过 request

    $value = $request->session()->get('key', 'default');
    

    第二种,使用 global session helper

    $value = session('key', 'default');
    

    url()->previous()

    https://laravel.com/docs/5.5/urls

    // Get the current URL without the query string...
    echo url()->current();
    // Get the current URL including the query string...
    echo url()->full();
    // Get the full URL for the previous request...
    echo url()->previous();
    

    但是,需要注意的是 url()->previous() 在实际运行中,并没有被用到。真正被用到的是 url.intended。

    测试一下,在 login 登录页面

    \Log::info(url()->previous());
    \Log::info(session('url.intended'));
    
    local.INFO: http://localhost:8000/
    local.INFO: http://localhost:8000/cart
    
    

    会看到,url()->previous() 得到的是被 route auth 拦住的之前的页面,而不是拦住将去往的页面,后者才是我们想获取到的。

    url.intended

    我并没有找到官方的文档,于是搜索了一下代码

    grep "url\.intended" -r vendor/laravel
    vendor/laravel/framework/src/Illuminate/Routing/Redirector.php:        $this->session->put('url.intended', $this->generator->full());
    vendor/laravel/framework/src/Illuminate/Routing/Redirector.php:        $path = $this->session->pull('url.intended', $default);
    

    Redirector.php

        /**
         * Create a new redirect response, while putting the current URL in the session.
         *
         * @param  string  $path
         * @param  int     $status
         * @param  array   $headers
         * @param  bool    $secure
         * @return \Illuminate\Http\RedirectResponse
         */
        public function guest($path, $status = 302, $headers = [], $secure = null)
        {
            $this->session->put('url.intended', $this->generator->full());
    
            return $this->to($path, $status, $headers, $secure);
        }
    
        /**
         * Create a new redirect response to the previously intended location.
         *
         * @param  string  $default
         * @param  int     $status
         * @param  array   $headers
         * @param  bool    $secure
         * @return \Illuminate\Http\RedirectResponse
         */
        public function intended($default = '/', $status = 302, $headers = [], $secure = null)
        {
            $path = $this->session->pull('url.intended', $default);
    
            return $this->to($path, $status, $headers, $secure);
        }
    

    url.intended 会记录 login 后将要跳转的 URL。

    redirect()->intended(‘dashboard’)

    https://laravel.com/docs/5.5/authentication

    return redirect()->intended('dashboard');
    

    Intended 函数的定义参考上面 Redirector.php 中的实现。

    所以等同于自己手写这个逻辑。

    在 LoginController 中,增加设置跳转页面的逻辑。

    public function index()
    {
        if(!session()->has('url.intended'))
        {
            session(['url.intended' => url()->previous()]);
        }
        return view('login');    
    }
    

    Login 验证完成之后,跳转逻辑修改为

    return redirect(session('url.intended', '/'));
    

    middleware 来处理大量的路由

    如果有大量的页面需要登录后才能访问,那么在 controller 中去逐个处理是否登录逻辑就非常浪费时间,简洁的实现方式是使用 middleware。

    如果需要跳转到一个自定义的 login 页面

    https://laracasts.com/discuss/channels/laravel/custom-login-page-redirection-from-middleware

    新建一个 middleware:

    class AuthMiddleware
    {
        public function handle($request, Closure $next)
        {
            if (auth()->guest()) {
                return redirect()->route('login.create');
            }
            return $next($request);
        }
    }
    

    App\Http\Kernel.php:

    protected $routeMiddleware = [
        'auth.custom' => \App\Http\Middleware\AuthMiddleware::class,
        ....
    

    参考

    https://stackoverflow.com/questions/29954791/laravel-5-after-login-redirect-back-to-previous-page

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式