这似乎是一个非常基本的流程,并且Laravel
对于基本的事情有很多很好的解决方案,我觉得我错过了一些东西。
用户单击需要身份验证的链接。Laravel 的auth过滤器启动并将它们路由到登录页面。用户登录,然后转到他们在“身份验证”过滤器启动之前尝试访问的原始页面。
有没有一种好方法可以知道他们最初试图访问哪个页面?由于 Laravel 是拦截请求的那个,我不知道它是否会在用户登录后跟踪某个地方以便于路由。
如果没有,我很想知道你们中的一些人是如何手动实现的。
检查下面斯科特的答案。
简单的说,
在 auth 中间件上:
// redirect the user to "/login"
// and stores the url being accessed on session
if (Auth::guest()) {
return redirect()->guest('login');
}
return $next($request);
登录操作:
// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return redirect()->intended('defaultpage');
}
在给出这个答案时,框架本身没有官方支持。现在你可以使用下面bgdrl指出的方法这个方法:(我试过更新他的答案,但似乎他不会接受)
在身份验证过滤器上:
// redirect the user to "/login"
// and stores the url being accessed on session
Route::filter('auth', function() {
if (Auth::guest()) {
return Redirect::guest('login');
}
});
登录操作:
// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return Redirect::intended('defaultpage');
}
你可以像这样实现它:
Route::filter('auth', function() {
// If there's no user authenticated session
if (Auth::guest()) {
// Stores current url on session and redirect to login page
Session::put('redirect', URL::full());
return Redirect::to('/login');
}
if ($redirect = Session::get('redirect')) {
Session::forget('redirect');
return Redirect::to($redirect);
}
});
// on controller
public function get_login()
{
$this->layout->nest('content', 'auth.login');
}
public function post_login()
{
$credentials = [
'username' => Input::get('email'),
'password' => Input::get('password')
];
if (Auth::attempt($credentials)) {
return Redirect::to('logged_in_homepage_here');
}
return Redirect::to('login')->with_input();
}
将重定向存储在 Session 上的好处是即使用户错过了键入他的凭据或者他没有帐户并且必须注册,也可以将其持久化。
这也允许除 Auth 之外的任何其他东西在会话上设置重定向,它会神奇地工作。
5.3 中的 Auth 更改使实现这一点更容易,并且与 5.2 略有不同,因为 Auth 中间件已移至服务容器。
/app/Http/Middleware/RedirectIfAuthenticated.php
稍微改变句柄函数,如下所示:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->intended('/home');
}
return $next($request);
}
唯一的区别在于第 4 行;默认情况下,它看起来像这样:
return redirect("/home");
由于 Laravel >= 5.3 在检查 Auth Guard 时会自动保存最后一个“预期”路由,因此它变为:
return redirect()->intended('/home');
这告诉 Laravel 在登录前重定向到最后一个预期页面,否则默认转到“/home”或您想发送它们的任何地方。
希望这对其他人有所帮助 - 5.2 和 5.3 之间的差异并不多,特别是在这个领域有很多。
我发现这两种很棒的方法可能对您非常有帮助。
Redirect::guest();
Redirect::intended();
您可以将此过滤器应用于需要身份验证的路由。
Route::filter('auth', function()
{
if (Auth::guest()) {
return Redirect::guest('login');
}
});
这种方法的基本作用是存储您尝试访问的页面,并将您重定向到登录页面。
用户通过身份验证后,您可以调用
return Redirect::intended();
它会将您重定向到您最初尝试访问的页面。
尽管我通常使用以下方法,但这是一个很好的方法。
Redirect::back()
你可以查看这个很棒的博客。
您可以使用Redirect::intended功能。它会将用户重定向到他们在被身份验证过滤器捕获之前尝试访问的 URL。如果预期的目标不可用,则可以为此方法提供一个备用 URI。
在登录/注册后:
return Redirect::intended('defaultpageafterlogin');
将您的 LoginControllers 构造函数更改为:
public function __construct()
{
session(['url.intended' => url()->previous()]);
$this->redirectTo = session()->get('url.intended');
$this->middleware('guest')->except('logout');
}
它会将您重定向回登录页面之前的页面(返回 2 页)。
我已经在我的语言选择器代码上使用了一段时间。只要您只需要返回 1 页,它就可以正常工作:
return Redirect::to(URL::previous());
它不是最强大的解决方案,但它超级简单,可以帮助解决一些难题。:)
return Redirect::intended('/');
这会将您重定向到项目的默认页面,即起始页面。
对于 laravel 5.* 试试这些。
return redirect()->intended('/');
或者
return Redirect::intended('/');
我稍微调整了您的(Vinícius Fragoso Pinheiro)代码,并将以下内容放在 filters.php
Route::filter('auth', function()
{
// If there's no user authenticated session
if (Auth::guest()) {
// Flash current url to session and redirect to login page
Session::flash('redirect', URL::full());
return Redirect::guest('login');
}
});
然后在我的 AuthController.php 中:
// Try to log the user in.
if (Auth::attempt($userdata)) {
if ($redirect = Session::get('redirect')) {
return Redirect::to($redirect);
} else {
// Redirect to homepage
return Redirect::to('your_default_logged_in_page')->with('success', 'You have logged in successfully');
}
} else {
// Reflash the session data in case we are in the middle of a redirect
Session::reflash('redirect');
// Redirect to the login page.
return Redirect::to('login')->withErrors(['password' => 'Password invalid'])->withInput(Input::except('password'));
}
请注意,'redirect'
如果存在身份验证问题,会话数据将被重新刷新。这样可以在任何登录事故期间保持重定向不变,但如果用户在任何时候点击离开,下一个登录过程不会被会话数据中断。
您还需要在显示登录表单时重新刷新数据AuthController
,否则链会中断:
public function showLogin()
{
// Reflash the session data in case we are in the middle of a redirect
Session::reflash('redirect');
// Show the login page
return View::make('auth/login');
}
以下方法适用于 Laravel 8。
/app/Http/Controllers/Auth/AuthenticatedSessionController.php
预期的 url 将存储在创建时的会话中:
/**
* Display the login view.
*
* @return \Illuminate\View\View
*/
public function create()
{
session(['url.intended' => url()->previous()]);
return view('auth.login');
}
成功登录后,如果会话中提供了预期的 URL,则重定向到它,否则重定向到默认 URL:
/**
* Handle an incoming authentication request.
*
* @param \App\Http\Requests\Auth\LoginRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
//in case intended url is available
if (session()->has('url.intended')) {
$redirectTo = session()->get('url.intended');
session()->forget('url.intended');
}
$request->session()->regenerate();
if ($redirectTo) {
return redirect($redirectTo);
}
return redirect(RouteServiceProvider::HOME);
}
利用Redirect;
然后使用这个:
return Redirect::back();
在 Laravel 5.8 中
在 App\Http\Controllers\Auth\LoginController 添加以下方法
public function showLoginForm()
{
if(!session()->has('url.intended'))
{
session(['url.intended' => url()->previous()]);
}
return view('auth.login');
}
在 App\Http\Middleware\RedirectIfAuthenticated 中将“return redirect('/home');”替换为以下内容
if (Auth::guard($guard)->check())
{
return redirect()->intended();
}
如果您使用 axios 或其他 AJAX javascript 库,您可能想要检索 url 并传递给前端
你可以用下面的代码做到这一点
$default = '/';
$location = $request->session()->pull('url.intended', $default);
return ['status' => 200, 'location' => $location];
这将返回一个 json 格式的字符串
对于Laravel 5.5和可能 5.4
在App\Http\Middleware\RedirectIfAuthenticated更改redirect('/home')
为redirect()->intended('/home')
句柄函数中:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->intended('/home');
}
return $next($request);
}
在App\Http\Controllers\Auth\LoginController创建showLoginForm()
函数如下:
public function showLoginForm()
{
if(!session()->has('url.intended'))
{
session(['url.intended' => url()->previous()]);
}
return view('auth.login');
}
这样,如果有另一个页面的意图,它将重定向到那里,否则它将重定向到主页。
Laravel 现在开箱即用地支持此功能! (我相信从 5.5 或更早的版本开始)。
向您添加一个__construct()
方法,Controller
如下所示:
public function __construct()
{
$this->middleware('auth');
}
登录后,您的用户将被重定向到他们最初打算访问的页面。
您还可以根据应用程序逻辑的需要添加 Laravel 的电子邮件验证功能:
public function __construct()
{
$this->middleware(['auth', 'verified']);
}
该文档包含一个非常简短的示例:
也可以通过使用except
oronly
选项来选择中间件应用到哪个控制器的方法。
示例except
:
public function __construct()
{
$this->middleware('auth', ['except' => ['index', 'show']]);
}
示例only
:
public function __construct()
{
$this->middleware('auth', ['only' => ['index', 'show']]);
}
有关中间件选项except
的更多信息:only
如果您正在使用另一个中间件,例如Admin中间件,您可以使用以下内容为url.intended设置会话:
基本上我们需要手动\Session::put('url.intended', \URL::full());
设置重定向。
例子
if (\Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
\Session::put('url.intended', \URL::full());
return redirect('login');
}
}
登录尝试
确保在登录尝试使用return \Redirect::intended('default_path');
我将以下方法与 Laravel 5.7 的自定义登录控制器和中间件一起使用,但我希望它适用于任何 laravel 5 版本
中间件内部
if (Auth::check()){
return $next($request);
}
else{
return redirect()->guest(route('login'));
}
内部控制器登录方法
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return redirect()->intended('/default');
}
如果您需要将意图的 url 传递给客户端,您可以尝试以下操作
if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
$intended_url= redirect()->intended('/default')->getTargetUrl();
$response = array(
'status' => 'success',
'redirectUrl' => $intended_url,
'message' => 'Login successful.you will be redirected to home..', );
return response()->json($response);
} else {
$response = array(
'status' => 'failed',
'message' => 'username or password is incorrect', );
return response()->json($response);
}
首先,您应该知道如何将用户重定向到“登录”路线:
return redirect()->guest('/signin');
不像这样:
return redirect()->intended('/signin');
// Also place this code into base controller in contract function, because ever controller extends base controller
if(Auth::id) {
//here redirect your code or function
}
if (Auth::guest()) {
return Redirect::guest('login');
}
对于 Laravel 5.7,您需要更改为:
中间件>RedirectIfAuthenticated.php
改变这个:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/admin');
}
return $next($request);
}
对此:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/yourpath');
}
return $next($request);
}
返回重定向('/你的路径');
Larvel 5.3 这实际上对我有用,只需更新 LoginController.php
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
Session::set('backUrl', URL::previous());
}
public function redirectTo()
{
return Session::get('backUrl') ? Session::get('backUrl') : $this->redirectTo;
}
参考:https ://laracasts.com/discuss/channels/laravel/redirect-to-previous-page-after-login
这是我对 5.1 的解决方案。我需要有人点击帖子上的“喜欢”按钮,重定向到登录,然后返回原始页面。如果他们已经登录,href
则“Like”按钮的“Like”按钮会被 JavaScript 拦截并转换为 AJAX 请求。
该按钮类似于<a href="/like/931">Like This Post!</a>
. /like/931
由需要auth
中间件的 LikeController 处理。
在 Authenticate 中间件(handle()
函数)中,在开头添加如下内容:
if(!str_contains($request->session()->previousUrl(), "/auth/login")) {
$request->session()->put('redirectURL', $request->session()->previousUrl());
$request->session()->save();
}
更改/auth/login
为用于登录的 URL。此代码将原始页面的 URL 保存在会话中,除非该 URL 是登录 URL。这是必需的,因为它看起来好像这个中间件被调用了两次。我不知道为什么或如果这是真的。但是,如果您不检查该条件,它将等于正确的原始页面,然后以某种方式偶然发现/auth/login
. 可能有一种更优雅的方法可以做到这一点。
然后,在LikeController
处理原始页面上按下的按钮的 URL 的控制器或任何控制器中:
//some code here that adds a like to the database
//...
return redirect($request->session()->get('redirectURL'));
这种方法超级简单,不需要重写任何现有函数,而且效果很好。Laravel 可能有一些更简单的方法可以做到这一点,但我不确定它是什么。在我的情况下使用该intended()
函数不起作用,因为 LikeController 还需要知道以前的 URL 是什么才能重定向回它。本质上是两个级别的向后重定向。
您是否在您的 routes.php 中尝试过这个?
Route::group(['middleware' => ['web']], function () {
//
Route::get('/','HomeController@index');
});
这在 laravel 8 中对我有用:
将此添加到您的 LoginController.php:
public function __construct()
{
session(['url.intended' => url()->previous()]);
$this->redirectTo = session()->get('url.intended');
$this->middleware('guest')->except('logout');
}
它会将您重定向 2 次,因此会重定向到您登录前的页面。
归功于@MevlütÖzdemir 的答案!
对于 Laravel 5.2(我之前没有使用过的版本)
将代码粘贴到文件 app\Http\Controllers\Auth\AurhController.php
/**
* Overrides method in class 'AuthenticatesUsers'
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showLoginForm()
{
$view = property_exists($this, 'loginView')
? $this->loginView : 'auth.authenticate';
if (view()->exists($view)) {
return view($view);
}
/**
* seve the previous page in the session
*/
$previous_url = Session::get('_previous.url');
$ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$ref = rtrim($ref, '/');
if ($previous_url != url('login')) {
Session::put('referrer', $ref);
if ($previous_url == $ref) {
Session::put('url.intended', $ref);
}
}
/**
* seve the previous page in the session
* end
*/
return view('auth.login');
}
/**
* Overrides method in class 'AuthenticatesUsers'
*
* @param Request $request
* @param $throttles
*
* @return \Illuminate\Http\RedirectResponse
*/
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
/*return to the previous page*/
return redirect()->intended(Session::pull('referrer'));
/*return redirect()->intended($this->redirectPath()); /*Larevel default*/
}
并导入命名空间:use Session;
如果您没有对文件 app\Http\Controllers\Auth\AurhController.php 进行任何更改,则可以将其替换为GitHub中的文件