场景
我自定义了一套 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 聊聊, 查看更多联系方式