Laravel Passport 登录无法使用 Jetstream Inertia 正确重定向

问题描述 投票:0回答:5

我已经使用 Laravel Passport 实现了一个 OAuth 系统,但是该系统的登录和所有身份验证均由具有 Inertia 的 Laravel Jetstream 处理。

当我想要请求代码(使用授权代码授予)时,我的应用程序将我重定向到我的 OAuth 服务器,该服务器在继续之前要求我登录,此屏幕是使用 Inertia (Vue) 登录 Laravel Jetstream 生成的屏幕。当我登录时,它会将我重定向到授权页面,但是这个重定向很奇怪,因为该页面显示在 Vue(惯性)页面内,浏览器中的 URL 不会更新,并且如果我接受授权请求它将我重定向回我的应用程序,但重定向位于同一个 Vue 页面内,我的意思是,URL 与我的 OAuth 服务器登录名相同,但视图是请求代码的我的应用程序。

我认为 Vue 中的重定向存在问题,因为授权页面没有使用 Inertia(Laravel Passport 的默认授权页面),我不知道如何修复它,你能帮我吗?

这是一张图片:

Bad Frame

正如你所看到的,它似乎是在模态中,但是是一个惯性错误页面,并且里面显示的是授权页面,是一个重定向错误,我不知道如何修复

laravel authentication laravel-passport inertiajs
5个回答
5
投票

我和你有同样的问题 我解决如下:

在文件中

AuthenticatedSessionController.php

/**
 * Handle an incoming authentication request.
 *
 * @param  \App\Http\Requests\Auth\LoginRequest  $request
 * @return \Illuminate\Http\RedirectResponse
 */
public function store(LoginRequest $request)
{
    $request->authenticate();

    $request->session()->regenerate();

    if ($request->session()->has('url.intended')) {
        return Inertia::location(session('url.intended'));
    }

    return redirect()->intended(RouteServiceProvider::HOME);
}

4
投票

我知道这是一个老问题 - 但我今天自己偶然发现了这个问题,发现这里有人问这个问题 - 它给了我一些如何解决它的信息 - 但在检查代码后,Laravel Jetstream/Fortify 中的一些事情似乎发生了变化下面的解决方案现在似乎更准确,更容易实现,因为提到的

AuthenticatedSessionController.php
位于包内,并且下面可以在用户代码中完成,而无需接触包代码本身。


我通过覆盖 Laravel Fortify 内部使用的

*Reponse
类来解决这个问题,下面是我在代码中的两个覆盖:

正常登录流程需要

LoginResponse

<?php

namespace App\Http\Responses;

use Inertia\Inertia;
use Laravel\Fortify\Http\Responses\LoginResponse as LoginResponseBase;

class LoginResponse extends LoginResponseBase
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        if ($request->session()->has('url.intended')) {
            return Inertia::location(session('url.intended'));
        }

        return parent::toResponse($request);
    }
}

添加

App\Providers\FortifyServiceProvider::register
以下行来覆盖它(不要忘记 use 语句):

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
use App\Http\Responses\LoginResponse;
...
public function register()
{
    ...
    $this->app->singleton(LoginResponseContract::class, LoginResponse::class);
    ...
}

使用 2FA 时需要

TwoFactorLoginResponse
,否则这也会像正常登录一样中断:

<?php

namespace App\Http\Responses;

use Inertia\Inertia;
use Laravel\Fortify\Http\Responses\TwoFactorLoginResponse as TwoFactorLoginResponseBase;

class TwoFactorLoginResponse extends TwoFactorLoginResponseBase
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        if ($request->session()->has('url.intended')) {
            return Inertia::location(session('url.intended'));
        }

        return parent::toResponse($request);
    }
}

添加

App\Providers\FortifyServiceProvider::register
以下行来覆盖它(不要忘记 use 语句):

use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;
use App\Http\Responses\TwoFactorLoginResponse;
...
public function register()
{
    ...
    $this->app->singleton(TwoFactorLoginResponseContract::class, TwoFactorLoginResponse::class);
    ...
}

上述更改只是确保给出正确的响应,以便 Inertia 根据其文档正确处理重定向: https://inertiajs.com/redirects#external-redirects


1
投票

如果请求来自 Inertia,您必须更改登录操作的默认视图。您可以在 FortifyServiceProvider 中完成。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Request;
use Illuminate\Support\ServiceProvider;
use Inertia\Inertia;
use Laravel\Fortify\Fortify;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Fortify::loginView(function () {
            if (Request::inertia()) {
                return Inertia::location(url()->current());
            }
            return view('auth.login');
        });
    }
}

0
投票

因为你使用的是惯性页面,所以不用 laravel 的重定向语法:

redirect($somewhere);

使用

use Inertia\Inertia;

// .... skip

Inertia::location($somewhere);

相反。


0
投票

分享我的解决方案,使用自定义身份验证: 网页.php

Route::get('/login', [LoginController::class, 'wechatLogin'])->name('login');
Route::post('/login', [LoginController::class, 'authenticate']);
Route::post('/logout', [LoginController::class, 'logout'])->name('logout');

LoingController.php

...
    public function authenticate(Request $request): RedirectResponse
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required'],
        ]);

        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();
            return redirect(route('dashboard'));
        }

        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ])->onlyInput('email');
    }
    public function logout(Request $request)
    {
        Auth::guard('web')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return Inertia::location('/');
    }
...
© www.soinside.com 2019 - 2024. All rights reserved.