首页 > 解决方案 > 如果不用于令牌,Sanctum 和 Laravel 的默认身份验证是否相同?

问题描述

我不太确定 Laravel 文档中的含义,所以我要求确定。

我们一方面有 Laravel 的默认身份验证,另一方面有 Sanctum 的默认身份验证。

据说 Sanctum 可以做 Tokens 或者简单地实现 auth。:

对于此功能,Sanctum 不使用任何类型的代币。相反,Sanctum 使用 Laravel 内置的基于 cookie 的会话身份验证服务。这提供了 CSRF 保护、会话身份验证以及防止身份验证凭据通过 XSS 泄漏的好处。只有当传入请求来自您自己的 SPA 前端 (Vue.js) 时,Sanctum 才会尝试使用 cookie 进行身份验证。

因此,如果从不使用令牌,Sanctum 与默认的身份验证方法基本相同,我说的对吗?基本上,它是否实现了默认身份验证并在需要时添加令牌?如果是这样,那么 sanctum 和 passport 有什么区别,因为它们做同样的事情,但据说 Sanctum 是轻量级的。这实际上是什么意思?

谢谢阅读

标签: laravellaravel-5eloquent

解决方案


因此,如果从不使用 Token,Sanctum 与默认的 Authentication 方法基本相同,我说的对吗?

是的,它使用 laravel 的默认身份验证。

看看 sanctum 守卫(下面的代码取自 github。它最后一次提交是在 4 月 11 日,sanctum 2.x)

<?php

namespace Laravel\Sanctum;

use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Http\Request;

class Guard
{
    /**
     * The authentication factory implementation.
     *
     * @var \Illuminate\Contracts\Auth\Factory
     */
    protected $auth;

    /**
     * The number of minutes tokens should be allowed to remain valid.
     *
     * @var int
     */
    protected $expiration;

    /**
     * Create a new guard instance.
     *
     * @param  \Illuminate\Contracts\Auth\Factory  $auth
     * @param  int  $expiration
     * @return void
     */
    public function __construct(AuthFactory $auth, $expiration = null)
    {
        $this->auth = $auth;
        $this->expiration = $expiration;
    }

    /**
     * Retrieve the authenticated user for the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    public function __invoke(Request $request)
    {
        if ($user = $this->auth->guard(config('sanctum.guard', 'web'))->user()) {
            return $this->supportsTokens($user)
                        ? $user->withAccessToken(new TransientToken)
                        : $user;
        }

        if ($token = $request->bearerToken()) {
            $model = Sanctum::$personalAccessTokenModel;

            $accessToken = $model::findToken($token);

            if (! $accessToken ||
                ($this->expiration &&
                 $accessToken->created_at->lte(now()->subMinutes($this->expiration)))) {
                return;
            }

            return $this->supportsTokens($accessToken->tokenable) ? $accessToken->tokenable->withAccessToken(
                tap($accessToken->forceFill(['last_used_at' => now()]))->save()
            ) : null;
        }
    }

    /**
     * Determine if the tokenable model supports API tokens.
     *
     * @param  mixed  $tokenable
     * @return bool
     */
    protected function supportsTokens($tokenable = null)
    {
        return $tokenable && in_array(HasApiTokens::class, class_uses_recursive(
            get_class($tokenable)
        ));
    }
}

如果你检查_invoke()方法,

    if ($user = $this->auth->guard(config('sanctum.guard', 'web'))->user()) {
        return $this->supportsTokens($user)
                    ? $user->withAccessToken(new TransientToken)
                    : $user;
    }

经过身份验证的用户是使用

$user = $this->auth->guard(config('sanctum.guard', 'web'))->user()

在检查了 sanctum 配置文件后,目前没有sanctum.guard配置(可能是为了将来的某个版本),所以 sanctumweb默认检查守卫,所以它基本上和你的默认 web 路由做同样的事情。

但是你误解了圣所的用途。Sanctum 用于 API 身份验证,而不用于 Web 身份验证(尽管它也可以用于 Web 身份验证)。Sanctum 的非令牌身份验证使您的 SPA 能够使用与移动应用程序(使用令牌身份验证)相同的 API,而无需令牌并提供 csrf 和基于会话的身份验证的好处。

为了帮助您更好地理解,假设您已经构建了一个使用令牌的 API(如果它已经使用 sanctum 作为令牌,这会使事情变得更简单)进行身份验证。现在您希望构建一个使用相同 API 的 SPA(可以在 laravel 项目本身内部构建,也可以是在同一域或不同域上构建的单独项目),但由于这将由您构建,因此它是一个受信任的站点,因此您不希望它使用令牌,而是使用 laravel 的默认基于会话的身份验证以及 csrf 保护,同时还使用相同的 api 路由。SPA 将通过 ajax 与服务器通信。您还希望确保仅允许您的 SPA 使用基于会话的身份验证,而不允许其他第三方站点使用它。

所以这就是 Sanctum 的用武之地。您只需要将 Sanctum 中间件添加到您的api路由组app/Http/Kernel.php

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

然后配置 sanctum 以允许您的 SPA 域并配置 cors(查看文档以了解如何执行此操作)。然后只需将auth:sanctum中间件添加到您的路由中,您就完成了服务器端设置。

现在,如果请求具有令牌或有状态(会话 cookie),这些路由将对用户进行身份验证。

现在您的 SPA 可以在没有令牌的情况下与您的 API 进行通信。

要获得csrf保护,csrf-cookie先调用请求,这会在你的cookies中设置一个csrf token,axios会自动附加到后续请求中

axios.get('/sanctum/csrf-cookie').then(response => {
    // Login...
})

圣所和护照有什么区别,因为它们做同样的事情,但据说圣所是轻量级的。

好吧,就像它说的那样,圣所是轻量级的。这是因为 Passport 提供了完整的 Oauth 功能,而 Sanctum 只专注于创建和管理令牌。为了简单地解释 Oauth,您必须在不同的站点上看到过这些Sign in with Google, Sign in with Facebook, Sign in with Github,然后您可以使用您的 google/facebook/github 帐户将其签名到这些站点。这是可能的,因为 Google、Facebook 和 Github 提供了 Oauth 功能(只是一个简单的例子,不做太多细节)。对于大多数网站,您并不需要 Passport,因为它提供了许多您不需要的功能。对于简单的 api 身份验证,Sanctum 绰绰有余


推荐阅读