Laravel 8:在API中使用Fortify

17

Laravel Fortify可以在API的情况下使用吗?据我所知,虽然Fortify是无头的(即不包括UI层),但它允许我们自定义登录和注册页面,但成功验证后它会自动重定向到主页。尽管主页是可自定义的,但这不符合API登录的常规工作方式。它应该只返回JSON格式的成功令牌而不进行任何重定向。

Fortify中有一个authenticateUsing函数,但即使如此,它也只允许我们自定义身份验证逻辑而不能自定义返回的数据。重定向仍由Fortify执行。

我如何在REST API的情况下使用Fortify?

注意:我将从我的Vue前端应用程序中使用它。我还要引入Sanctum,但在此之前,我想看看是否可以使用Fortify进行常规基于令牌的身份验证,而无需编写自己的登录、注册和注销路由和控制器函数。


你解决了吗?有示例吗?我不想使用registerView(),这可行吗? - NicoHood
是的,我做到了。请查看已接受的答案及其评论。如果您正在使用诸如Vue之类的前端框架,只需使用Sanctum为您提供基于会话的身份验证系统即可。在客户端上,开发自己的注册/登录UI并使用axios来处理会话cookie。然后,您可以调用API函数,获取JSON编码响应并在客户端上处理它。 - dotNET
3个回答

15

身份验证可以是基于会话(Session-based)的,也可以是基于令牌(Token-based)的。

Laravel Fortify仅提供用于基于会话身份验证所需的后端逻辑,因此不适用于基于令牌的API身份验证。

如果您需要基于令牌的API身份验证,可以根据您的需求使用SanctumPassport。但无论哪种情况,都需要编写一些代码。

如果您决定使用Laravel Passport,则我有一个可能会有用的样板项目:https://github.com/pktharindu/laravel-api-boilerplate-passport


2
是的。这就是让人困惑的地方。使用Fortify时,我们可以获得基本的身份验证路由和服务(如注册、登录、重置密码等),但正如你所说,这仅适用于基于会话的身份验证。另一方面,Sanctum可以同时进行会话和令牌身份验证,但不提供任何身份验证路由。我的理解是否正确? - dotNET
2
我在 Laravel 7 中的项目中已经使用了 Passport,并为我的 API 创建了所有这些身份验证路由。随着 Laravel 8 的推出,他们建议我们转向 Sanctum,除非我们需要完整的 OAuth 实现。因此,我阅读了文档并得出结论,Sanctum 将为我处理令牌管理,而 Fortify(作为无头服务)将为我提供身份验证路由和服务。因此,有了这两个包,我将摆脱自定义的登录/注销功能以及 Passport。看起来我的理解是不正确的。 - dotNET
4
如果您有单独的前端应用程序,那么Fortify基本上是无用的。您可以使用Sanctum或Passport。但是您将不得不自己设置路由。如果符合您的需求并且您是从头开始,使用Sanctum是有意义的。但是如果您已经安装了Passport,我建议您保持原样,因为转换到Sanctum并不能比Passport提供任何优势。 - P. K. Tharindu
谢谢,那很有道理。 - dotNET

13

只需设置 'Accept' 标头为 'application/json' 或 'application/javascript',fortify 就会响应 json 格式的主体而不是重定向。

顺便说一句,对于 SPA,使用 Sanctum 而不是 Passport 更容易保持令牌的安全性。搜索有关在 SPA 中存储 API 令牌的位置,您将了解原因。


请问您能否提供一个简单的示例,例如如何使用/register端点?我目前不知道如何使用它,无论是使用简单的curl还是postman。似乎您总是必须先调用registerView(),但我不想使用它。 - NicoHood

2

在我的情况下,重定向的原因是 Laravel 的默认RedirectIfAuthenticated提供者。

默认情况下,在 Laravel8 中该提供者如下:

<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string[]|null  ...$guards
     * @return mixed
     */
    public function handle($request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {
                return redirect(RouteServiceProvider::HOME);
            }
        }

        return $next($request);
    }
}

只需将默认的foreach替换为以下代码:

foreach ($guards as $guard) {
    if (Auth::guard($guard)->check()) {
        if ($request->expectsJson()) {
            return response()->json([
               'error' => 'Already authenticated.'
            ], 406);
        }
        return redirect(RouteServiceProvider::HOME);
    }
}

请不要忘记,在使用$request->expectsJson()时,您应该在请求头中包含Accept: application/json

注意保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接