Optimize anonymous public sessions
This commit is contained in:
122
app/Http/Middleware/ConditionalStartSession.php
Normal file
122
app/Http/Middleware/ConditionalStartSession.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ConditionalStartSession extends StartSession
|
||||
{
|
||||
public function handle($request, Closure $next): mixed
|
||||
{
|
||||
if (! $request instanceof Request || ! config('skinbase-sessions.enabled', true)) {
|
||||
return parent::handle($request, $next);
|
||||
}
|
||||
|
||||
if ($this->shouldSkipSession($request)) {
|
||||
$request->attributes->set('skinbase.session_skipped', true);
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
if ($response instanceof Response && config('skinbase-sessions.debug_header', false)) {
|
||||
$response->headers->set('X-Skinbase-Session', 'skipped');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$request->attributes->set('skinbase.session_skipped', false);
|
||||
|
||||
$response = parent::handle($request, $next);
|
||||
|
||||
if ($response instanceof Response && config('skinbase-sessions.debug_header', false)) {
|
||||
$response->headers->set('X-Skinbase-Session', 'started');
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function shouldSkipSession(Request $request): bool
|
||||
{
|
||||
if (! $this->isSafeReadMethod($request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->hasExistingSessionCookie($request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->matchesAnyPath($request, config('skinbase-sessions.always_session_paths', []))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->matchesAnyPath($request, config('skinbase-sessions.public_paths', []))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config('skinbase-sessions.skip_anonymous_public_get', true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return config('skinbase-sessions.skip_known_crawlers_on_public_get', true)
|
||||
&& $this->isKnownCrawler($request);
|
||||
}
|
||||
|
||||
protected function isSafeReadMethod(Request $request): bool
|
||||
{
|
||||
return in_array($request->getMethod(), ['GET', 'HEAD'], true);
|
||||
}
|
||||
|
||||
protected function hasExistingSessionCookie(Request $request): bool
|
||||
{
|
||||
$cookieName = config('session.cookie');
|
||||
|
||||
return is_string($cookieName)
|
||||
&& $cookieName !== ''
|
||||
&& $request->cookies->has($cookieName);
|
||||
}
|
||||
|
||||
protected function matchesAnyPath(Request $request, array $patterns): bool
|
||||
{
|
||||
foreach ($patterns as $pattern) {
|
||||
if (! is_string($pattern) || $pattern === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($pattern === '/' && $request->path() === '/') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$normalizedPattern = trim($pattern, '/');
|
||||
|
||||
if ($normalizedPattern !== '' && $request->is($normalizedPattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function isKnownCrawler(Request $request): bool
|
||||
{
|
||||
$userAgent = strtolower((string) $request->userAgent());
|
||||
|
||||
if ($userAgent === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (config('skinbase-sessions.bot_user_agent_keywords', []) as $keyword) {
|
||||
$normalizedKeyword = strtolower((string) $keyword);
|
||||
|
||||
if ($normalizedKeyword !== '' && str_contains($userAgent, $normalizedKeyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user