Laravel Passport Set会议

时间:2018-08-19 08:44:55

标签: laravel laravel-passport

我试图通过Laravel护照设置会话时遇到错误

“消息”:“未根据请求设置会话存储。”, “ exception”:“ RuntimeException”,

2 个答案:

答案 0 :(得分:0)

Laravel Passport是用于laravel的基于令牌的身份验证程序包

  

API通常使用令牌来验证用户身份,并且不维护   请求之间的会话状态。 Laravel使API身份验证成为可能   使用Laravel Passport轻轻松松,它提供了完整的OAuth2服务器   只需几分钟即可实现Laravel应用程序的实现。

默认情况下,包括oAuth2在内的几乎所有基于令牌的系统都是无状态的,这意味着没有会话与其关联,

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

这就是为什么使用laravel护照时无法设置会话

答案 1 :(得分:0)

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

1。在StartSession之后添加auth:api中间件。

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

EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,

然后从中删除\Illuminate\View\Middleware\ShareErrorsFromSession::class middlewarePriority受保护的财产。没有这个StartSession中间件,将在{strong>之前 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,
        ],
    ];
}

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);
    }
}

然后在auth:api之后添加以下三行。

EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSessionShared::class,

此方法中的一个重要说明是调用$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) {
            }
        });
    }
}

更新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,
        ],
    ];