Предотвращение сеансов для маршрутов в Laravel (пользовательская обработка сеанса по требованию)

Я создаю API для своего приложения для Android, используя laravel и драйвер сеанса по умолчанию, установленный в REDIS.

Я нашел здесь хорошую статью http://dor.ky/laravel-prevent-sessions-for-routes-via-a-filter/, которая служит цели.

Однако, когда я ударяю URL-адрес, он также попадает в redis и генерирует ключ, который пуст. Теперь я хочу избежать создания пустых ключей сеанса в redis. В идеале это не должно ударить redis. Как я могу это сделать?

Можно ли настроить sessios таким образом, чтобы сеансы генерировались только для определенных маршрутов (или отключались для определенных маршрутов)?

Я могу объяснить больше с конкретным вариантом использования, пожалуйста, дайте мне знать.

Ответ 1

Его очень легко использовать промежуточное ПО в Laravel 5, мне нужен был любой запрос с ключом API, чтобы не иметь сеанс, и я просто сделал:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Session\Middleware\StartSession as BaseStartSession;

class StartSession extends BaseStartSession
{

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(\Request::has('api_key'))
        {
            \Config::set('session.driver', 'array');
        }
        return parent::handle($request, $next);
    }
}

Также вам необходимо расширить SessionServiceProvider следующим образом:

<?php namespace App\Providers;

use Illuminate\Session\SessionServiceProvider as BaseSessionServiceProvider;

class SessionServiceProvider extends BaseSessionServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerSessionManager();

        $this->registerSessionDriver();

        $this->app->singleton('App\Http\Middleware\StartSession');
    }
}

и поместите в свой config/app.php под providers:

'App\Providers\SessionServiceProvider',

Также вы должны изменить его в своем файле ядра: App/Http/Kernel.php, в разделе $middlewareGroups измените запись по умолчанию, \Illuminate\Session\Middleware\StartSession::class, на новый класс \App\Http\Middleware\StartSession::class,.

Ответ 2

В Laravel 5 просто не используйте StartSession, ShareErrorsFromSession и VerifyCsrfToken middlewares.

В моем приложении я переместил эти три middlewares из группы web в новую группу stateful, а затем включил эту группу stateful в маршруты, которые должны знать о сеансе (в дополнение к web во всех случаях, по крайней мере, в моем приложении). Другие маршруты относятся к группам web или api.

Теперь, когда вы делаете запросы к маршрутам, которые не используют cookie файлы промежуточной группы stateful, файлы cookie не отправляются обратно.

Ответ 3

Самый простой способ добиться этого - сделать свое собственное промежуточное ПО AppStartSession, которое подклассы Illuminate\Session\Middleware\StartSession и заменить класс, используемый в kernel.php. Единственный метод, который необходимо переопределить в вашем подклассе, - sessionConfigured(), для которого вы можете вернуть false, чтобы отключить сеанс или родительский:: sessionConfigured(), чтобы разрешить его.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Session\Middleware\StartSession;

class AppStartSession extends StartSession
{
    protected function sessionConfigured(){
        if(!\Request::has('api_key')){
            return false;
        }else{
            return parent::sessionConfigured();
        }
    }
}

kernel.php(см. комментарий ***, где выполняется изменение)

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application global HTTP middleware stack.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,

       // *** Replace start session class
       // \Illuminate\Session\Middleware\StartSession::class,
        \App\Http\Middleware\AppStartSession::class,

        // *** Also comment these ones that depend on there always being a session.
        //\Illuminate\View\Middleware\ShareErrorsFromSession::class,
        //\App\Http\Middleware\VerifyCsrfToken::class,
    ];

    /**
     * The application route middleware.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    ];
}

Не сражайтесь с каркасом, обнимайте его!

Ответ 4

Начиная с Laravel 5.2, когда были введены группы промежуточного программного обеспечения, вы можете отключить сеанс для определенных маршрутов, указав их вне группы "промежуточного программного обеспечения" (включая промежуточное ПО StartSession, ответственное за обработку сеанса). Как и в последних версиях версии 5.2.x, весь файл default.php по умолчанию обернут группой промежуточного программного обеспечения "web", вам нужно внести некоторые изменения в файл app/Providers/RouteServiceProvider.php, как описано здесь.

Ответ 5

Кажется, есть способ выполнить это, используя обратный вызов отклонения сеанса.

Соответствующие источники...

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/Application.php#L655

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/Application.php#L660

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Session/Middleware.php#L60

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Session/Middleware.php#L97

Я не могу найти много ссылок на это по всему Интернету, но, прочитав больше через источник, кажется, что если отказ от вызова callback возвращает правдивое значение, сеанс будет вынужден использовать драйвер массива для запроса, а не независимо от того, что настроено. Ваш обратный вызов также получает текущий запрос, поэтому вы можете сделать некоторую логику на основе параметров запроса.

Я тестировал это только на локальной установке Laravel 4.2, но, похоже, это работает. Вам просто нужно привязать функцию к session.reject.

Сначала создайте SessionRejectServiceProvider (или что-то в этом роде)

<?php

use \Illuminate\Support\ServiceProvider;

class SessionRejectServiceProvider extends ServiceProvider {

    public function register()
    {
        $me = $this;
        $this->app->bind('session.reject', function($app)use($me){
            return function($request)use($me){
                return call_user_func_array(array($me, 'reject'), array($request));
            };
        });
    }

    // Put the guts of whatever you want to do in here, in this case I've
    // disabled sessions for every request that is an Ajax request, you
    // could do something else like check the path against a list and
    // selectively return true if there a match.
    protected function reject($request)
    {
        return $request->ajax();
    }

}

Затем добавьте его своим провайдерам в приложение /config/app.php

<?php

return array(
   // ... other stuff
   'providers' => array(
       // ... existing stuff...
       'SessionRejectServiceProvider',
   ),
);

Изменить/Подробнее

Конечным результатом является то, что метод reject() вызывается при каждом запросе вашего приложения до начала сеанса. Если ваш метод reject() возвращает true, сеансы будут установлены на драйвер массива и в основном ничего не делают. Вы можете найти много полезной информации для параметра $request, чтобы определить это, здесь ссылка API для объекта запроса в 4.2.

http://laravel.com/api/4.2/Illuminate/Http/Request.html

Ответ 6

Я пытаюсь выполнить аналогичную функцию.

Наш API является апатридом, за исключением 1 маршрута - корзины версии 1.

В итоге я установил 'driver' в app/config/session.php, как это...

'driver' => 'v1/cart' === Request::getDecodedPath() ? 'native' : 'array',

Ничего волшебного. Первоначально мы, однако, использовали фильтр before, но этого не происходило достаточно рано.

Кажется, это простой способ сделать что-то, но мне может быть что-то не хватает.

Включение коммутатора в конфигурацию кажется легким местом для других разработчиков, чтобы увидеть, что такое драйвер, тогда как его размещение в провайдере услуг настолько убрано с пути, не зная, какие поставщики услуг установлены и с чем они взаимодействуют, было бы гораздо сложнее отладить.

В любом случае. Надеюсь, это будет полезно.

Как указано ниже... НЕ СЛЕДУЙТЕ СВОЕГО КОНФИГУРА, ЕСЛИ ДИНАМИКА.

Это приводит к ограниченному использованию. Как только нам больше не нужно поддерживать v1/cart, мы отбросим этот маршрут, а затем вернемся к статической конфигурации.

Ответ 7

По умолчанию в Laravel есть две группы маршрутов, называемые web и api, по умолчанию группа маршрутов api без сессии.

Таким образом, мы можем записать любую роль routes/api.php, не будем использовать сеанс по умолчанию.

Если вы не хотите использовать URL-адрес префикса API, мы можем изменить app\Providers\RouteServiceProvider добавить новую группу, например:

Route::middleware('api')
    ->namespace($this->namespace)
    ->group(base_path('routes/static.php'));

Теперь вы можете размещать любые маршруты в файле routes/static.php чтобы не использовать сессию.

Надеюсь полезно.