Laravel Passport Set 会话

Alo*_*rma 5 laravel laravel-passport

当我尝试通过 laravel 护照设置会话时出现以下错误

"message": "会话存储未根据请求设置。", "exception": "RuntimeException",

vba*_*osh 6

这可以通过多种方式完成。

1. 后添加StartSession中间件auth:api

这是最直接的解决方案。在 之后添加以下三行auth:api

EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
Run Code Online (Sandbox Code Playgroud)

然后\Illuminate\View\Middleware\ShareErrorsFromSession::classmiddlewarePriority受保护的财产中移除。没有这个StartSession中间件将在之前 获得控制权auth,更重要的是,在EncryptCookies中间件之前,这基本上总是会导致一个新的会话。

<?php

namespace App\Http;

class Kernel extends HttpKernel
{
    // Copy this values from
    // \Illuminate\Foundation\Http\Kernel::$middlewarePriority
    // then remove or comment line with StartSession. Without it,
    // StartSession middleware will get control right before Auth.
    // Which, basically, will create a new session because at this
    // time cookies are still encrypted.
    protected $middlewarePriority = [
        // \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Auth\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            ...
        ],
        'api' => [
            'throttle:120,1',
            'bindings',
            'auth:api', // https://laravel.com/docs/5.7/passport#protecting-routes

            // Add the following three middleware right after `auth`
            // in order to have a session.
            EncryptCookies::class,
            AddQueuedCookiesToResponse::class,
            StartSession::class,
        ],
    ];
}
Run Code Online (Sandbox Code Playgroud)

2. 创建自己的StartSession中间件。

拥有自己的中间件来启动会话将使您无需覆盖middlewarePriority.

首先,创建一个新类。

<?php

namespace App\Http\Middleware;

use Illuminate\Contracts\Foundation\Application;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\SessionManager;

class StartSessionShared extends StartSession
{
    public function __construct(Application $app, SessionManager $manager)
    {
        parent::__construct($manager);
        $app->singleton(StartSessionShared::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在auth:api.

EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSessionShared::class,
Run Code Online (Sandbox Code Playgroud)

此方法中的一个重要注意事项是调用$app->singleton. 如果没有它,Laravel 将始终创建此类的新实例。这将导致\Illuminate\Session\Middleware\StartSession::terminate跳过保存会话的方法。

3. 创建自己的StartSessionReadonly中间件。

如果您只想在web 守卫之间共享会话api并且不打算以任何方式改变其值,那么这是一个不错的选择。这是我的情况。

创建以下StartSessionReadonly中间件。然后在api警卫中使用它而不是StartSession两个它的朋友。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\SessionManager;

/**
 * Middleware for sharing session between `web` and `api` guards.
 * Since the latter is essentially stateless, the session from
 * `web` is shared as readonly.
 *
 * @package App\Http\Middleware
 */
class StartSessionReadonly extends StartSession
{
    protected $encrypter;

    public function __construct(Encrypter $encrypter, SessionManager $manager)
    {
        parent::__construct($manager);
        $this->encrypter = $encrypter;
    }

    public function handle($request, Closure $next)
    {
        // If a session driver has been configured, we will need to start the session here
        // so that the data is ready for an application. Note that the Laravel sessions
        // do not make use of PHP "native" sessions in any way since they are crappy.
        if ($this->sessionConfigured()) {
            $request->setLaravelSession($this->startSession($request));
        }

        return $next($request);
    }

    public function getSession(Request $request)
    {
        return tap($this->manager->driver(), function (Session $session) use ($request) {
            $payload = $request->cookies->get($session->getName());
            $unserialize = EncryptCookies::serialized($session->getName());
            try {
                $session->setId($this->encrypter->decrypt($payload, $unserialize));
            }
            catch (DecryptException $exception) {
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

更新后,app/Http/Kernel.php您将拥有所有 api 的只读会话。

<?php

namespace App\Http;

class Kernel extends HttpKernel
{
    [...]

    /****
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        [...]
        'api' => [
            'throttle:120,1',
            'bindings',
            'auth:api', // https://laravel.com/docs/5.7/passport#protecting-routes
            StartSessionReadonly::class,
        ],
    ];
Run Code Online (Sandbox Code Playgroud)


Sho*_*obi 3

Laravel Passport 是 Laravel 的基于令牌的身份验证包

API 通常使用令牌来验证用户身份,并且不维护请求之间的会话状态。Laravel 使用 Laravel Passport 使 API 身份验证变得轻而易举,它在几分钟内为您的 Laravel 应用程序提供了完整的 OAuth2 服务器实现。

几乎所有基于令牌的系统(包括 oAuth2)默认情况下都是无状态的,这意味着没有附加会话,

这意味着没有会话存储。您只能依靠每个请求提供的令牌来验证用户身份。

这就是为什么你在使用 Laravel Passport 时无法设置会话

  • 我想如果你稍微修改一下,你可以在护照中启用会话。但这将违背使用 REST API 的目的,REST 是无状态的。 (2认同)