在 Laravel 中阻止路由会话(自定义按需会话处理)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26473106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:18:34  来源:igfitidea点击:

Prevent Sessions For Routes in Laravel (Custom on-demand session handling)

phpsessionlaravellaravel-4laravel-routing

提问by ???? ???p

I am building APIs for my Android app using laravel and default session driver set to REDIS.

我正在使用 laravel 和设置为 REDIS 的默认会话驱动程序为我的 Android 应用程序构建 API。

I found a good article here http://dor.ky/laravel-prevent-sessions-for-routes-via-a-filter/which sort of serves the purpose.

我在这里找到了一篇很好的文章http://dor.ky/laravel-prevent-sessions-for-routes-via-a-filter/哪一种可以达到目的。

However when ever I hit the url it also hits the redis and generates the key which is empty. Now I want avoid creating empty session keys in redis. Ideally it should not hit the redis How can I do that?

但是,当我点击 url 时,它也会点击 redis 并生成空的密钥。现在我想避免在 redis 中创建空会话密钥。理想情况下它不应该击中 redis 我该怎么做?

Can we customise sessios in a way so that sessions are generated only for specific routes (or disable for specific routes)?

我们能否以某种方式自定义 sessios,以便仅为特定路由生成会话(或禁用特定路由)?

I can explain more with specific use case, please let me know.

我可以用具体的用例解释更多,请让我知道。

回答by LukePOLO

Its really easy using the middleware in Laravel 5, I needed any request with an API key not to have a session and I simply did :

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

Also you will need to extend the SessionServiceProvider as follows:

您还需要按如下方式扩展 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');
    }
}

and place in your config/app.phpunder providers:

并放置在您的config/app.phpproviders

'App\Providers\SessionServiceProvider',

Also you must change it in your kernel file: App/Http/Kernel.php, in the $middlewareGroupssection change the default entry, \Illuminate\Session\Middleware\StartSession::class,to your new class \App\Http\Middleware\StartSession::class,.

此外,您必须在内核文件中更改它:App/Http/Kernel.php,在$middlewareGroups将默认条目更改为\Illuminate\Session\Middleware\StartSession::class,新类的部分中\App\Http\Middleware\StartSession::class,

回答by tremby

In Laravel 5, just don't use the StartSession, ShareErrorsFromSession, and VerifyCsrfTokenmiddlewares.

在Laravel 5,只是不使用StartSessionShareErrorsFromSessionVerifyCsrfToken中间件。

In my application I've moved these three middlewares from the webgroup to a new statefulgroup, and then I have included this statefulgroup on routes which need to know about the session (in addition to webin all cases, in my app at least). The other routes belong to either the webor apigroups.

在我的应用程序中,我已将这三个中间件从web组移动到一个新stateful组,然后我将此stateful组包含在需要了解会话的路由中(除了web在所有情况下,至少在我的应用程序中)。其他路由属于webapi组。

Now when making requests to the routes which are not using the statefulmiddleware group session cookies are not sent back.

现在,当向不使用stateful中间件组会话 cookie的路由发出请求时,不会发回。

回答by Denis

Since Laravel 5.2, when middleware groups were introduced, you may disable session for certain routes by defining them outside of the "web" middleware group (which includes the StartSession middleware responsible for session handling). As on latest 5.2.x versions the whole default routes.php file is wrapped with "web" middleware group, you need to make some modification in app/Providers/RouteServiceProvider.phpfile, as described here.

从 Laravel 5.2 开始,当引入中间件组时,您可以通过在“web”中间件组(包括负责会话处理的 StartSession 中间件)之外定义它们来禁用某些路由的会话。由于对最新的5.2.x版本的全默认routes.php文件文件是包裹着“网络”中间件组,你需要做出一些修改的app/Providers/RouteServiceProvider.php文件,描述在这里

回答by malhal

The simplest way to achieve this is to Make your own AppStartSession middleware that subclasses Illuminate\Session\Middleware\StartSession and the replace the class being used in kernel.php. The only method you need to override in your subclass is sessionConfigured() for which you can return false to disable the session or parent::sessionConfigured() to allow it.

实现此目的的最简单方法是制作您自己的 AppStartSession 中间件,该中间件将 Illuminate\Session\Middleware\StartSession 子类化,并替换 kernel.php 中正在使用的类。您需要在子类中覆盖的唯一方法是 sessionConfigured(),您可以返回 false 以禁用会话或 parent::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 (see *** comment for where the change is done)

kernel.php(有关更改完成的位置,请参阅 *** 注释)

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's 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's 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,
    ];
}

Don't fight the framework, embrace it!

不要与框架抗争,拥抱它!

回答by codenamegary

There appears to be a way to accomplish this using a session reject callback.

似乎有一种方法可以使用会话拒绝回调来完成此操作。

Relevant sources...

相关资源...

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#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/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#L60

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

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

I can't find many references to this around the web, but reading more through the source it appears that if the session reject callback returns a truthy value, the session will be forced to use an array driver for the request rather than whatever is configured. Your callback also gets the current request injected so you can do some logic based on the request parameters.

我在网络上找不到很多对此的引用,但是通过源阅读更多内容似乎如果会话拒绝回调返回一个真值,会话将被迫使用数组驱动程序来请求而不是任何配置. 您的回调还会注入当前请求,因此您可以根据请求参数执行一些逻辑。

I've only tested this on a local Laravel 4.2 install but it seems to work. You just need to bind a function to session.reject.

我只在本地 Laravel 4.2 安装上测试过这个,但它似乎有效。你只需要绑定一个函数到 session.reject。

First, create a SessionRejectServiceProvider (or something like that)

首先,创建一个 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's a match.
    protected function reject($request)
    {
        return $request->ajax();
    }

}

Then add it to your providers in your app/config/app.php

然后将它添加到您的 app/config/app.php 中的提供者

<?php

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

Edit / More Info

编辑/更多信息

The net result is that the reject() method is called on every request to your application, beforethe session is started. If your reject() method returns true, sessions will be set to the array driver and basically do nothing. You can find a lot of useful info the $request parameter to determine this, here's the API reference for the request object in 4.2.

最终结果是,会话开始之前,对应用程序的每个请求都会调用 reject() 方法。如果您的 reject() 方法返回 true,会话将被设置为数组驱动程序并且基本上什么都不做。您可以在 $request 参数中找到很多有用的信息来确定这一点,这里是 4.2 中请求对象的 API 参考。

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

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

回答by Richard A Quadling

I've been trying to accomplish a similar feature.

我一直在尝试实现类似的功能。

Our API is stateless except for 1 route - the version 1 cart.

我们的 API 是无状态的,除了 1 条路线 - 版本 1 购物车。

I ended up with setting 'driver'in the app/config/session.php like this ...

我最终'driver'在 app/config/session.php 中设置了这样的......

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

Nothing magic. Initially we though of using a before filter, but that wasn't happening early enough.

没什么神奇的。最初我们想使用 before 过滤器,但这还不够早。

It seems a simple way to do things, but I may be missing something.

这似乎是一种简单的做事方式,但我可能会遗漏一些东西。

Putting the switch in the config seems an easy place for other developers to see what the driver is whereas putting it in a service provider is so tucked out of the way, without knowing what service providers are installed and what they interact with, it would be far harder to debug.

将开关放在配置中似乎很容易让其他开发人员看到驱动程序是什么,而将它放在服务提供者中则太麻烦了,不知道安装了哪些服务提供者以及它们与什么交互,这将是调试起来要困难得多。

Anyway. Hope this is of some use.

反正。希望这有点用。

As pointed out below ... DO NOT CACHE YOUR CONFIG IF IT IS DYNAMIC.

正如下面所指出的......如果它是动态的,请不要缓存您的配置。

Which does lead to it being of limited use. As soon as we no longer need to support v1/cart, we will be dropping this route and then be back on a static config.

这确实导致它的用途有限。一旦我们不再需要支持 v1/cart,我们将删除此路由,然后返回静态配置。

回答by Avenger

Laravel default have two routes group called weband api, the api routes group default without session.

Laravel 默认有两个路由组叫做weband api,api 路由组默认没有会话。

So, we can write any route role to routes/api.php, will not use session default.

因此,我们可以将任何路由角色写入routes/api.php,不会使用会话默认值。

If not want to use the api prefix url, we can modify app\Providers\RouteServiceProvideradd a new group like this:

如果不想使用 api 前缀 url,我们可以app\Providers\RouteServiceProvider像这样修改添加一个新组:

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

Now you can place any routes into routes/static.phpfile will not to use session.

现在您可以将任何路由放入routes/static.php文件中,而不会使用会话。

Hope helpful.

希望有帮助。