No Laravel Sessions for Bots

2019-04-11 02:58发布

I'm having problems with a big Laravel project and the Redis storage. We store our sessions in Redis. We already have 28GB of RAM there. However, it still runs relatively fast to the limit, because we have very many hits (more than 250,000 per day) from search engine bots.

Is there any elegant way to completely disable sessions for bots? I have already implemented my own session middleware, which looks like this:

<?php

namespace App\Http\Middleware;

use App\Custom\System\Visitor;

class StartSession extends \Illuminate\Session\Middleware\StartSession
{
    protected function getSessionLifetimeInSeconds()
    {
        if(Visitor::isBot()) {
            return 1;
        }

        return ($this->manager->getSessionConfig()['lifetime'] ?? null) * 60;
    }

    protected function sessionIsPersistent(array $config = null)
    {
        if(Visitor::isBot()) {
            return false;
        }

        $config = $config ?: $this->manager->getSessionConfig();

        return ! in_array($config['driver'], [null, 'array']);
    }
}

This is my function for detecting bots:

public static function isBot()
    {
        $exceptUserAgents = [
            'Googlebot',
            'Bingbot',
            'Yahoo! Slurp',
            'DuckDuckBot',
            'Baiduspider',
            'YandexBot',
            'Sogou',
            'facebot',
            'ia_archiver',
        ];

        if(!request()->header('User-Agent') || !str_contains(request()->header('User-Agent'), $exceptUserAgents)) {
            return false;
        }

        return true;
    }

Unfortunately, this does not seem to work. Does anyone have a tip or experience here? Thank you very much!

2条回答
劫难
2楼-- · 2019-04-11 03:18

This is how I solved this for myself.

  1. Include a bot detection package using composer. I used this one: https://github.com/JayBizzle/Crawler-Detect

    composer require jaybizzle/crawler-detect

  2. Create a new middleware class

namespace App\Http\Middleware;

class NoSessionForBotsMiddleware
{
    public function handle($request, \Closure $next)
    {
        if ((new \Jaybizzle\CrawlerDetect\CrawlerDetect)->isCrawler()) {
            \Config::set('session.driver', 'array');
        }

        return $next($request);
    }
}
  1. Register the middleware before session middleware in the Kernel class:
protected $middlewareGroups = [
    'web' => [
        // ..
        NoSessionForBotsMiddleware::class,
        StartSession::class,
        // ..
    ],
    // ..
];
查看更多
做自己的国王
3楼-- · 2019-04-11 03:24

Your problem could be that you're not identifying robots correctly, so it would be helpful to provide the code for that.

Specific to writing middleware that disables sessions, you're much better off changing the session driver to the array driver as that driver does not persist sessions, instead of changing the configuration of the real session driver at runtime.

<?php

namespace App\Http\Middleware;

use App\Custom\System\Visitor;
use Illuminate\Support\Facades\Config;

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

        return $next($request);
    }
}
查看更多
登录 后发表回答