Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Laravel Sessions for Bots

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!

like image 557
TorbenL Avatar asked Dec 13 '22 15:12

TorbenL


2 Answers

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,
        // ..
    ],
    // ..
];
like image 169
Mārtiņš Briedis Avatar answered Dec 17 '22 22:12

Mārtiņš Briedis


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);
    }
}
like image 21
sam Avatar answered Dec 17 '22 23:12

sam