Действительно ли возможно использовать сессии PHP для аутентификации с помощью кеша nginx fastcgi?
Я недавно переключил экземпляр opencart с Apache+mod_php на nginx+fastcgi+php-fpm. Я пытался использовать кэширование для большинства страниц через fastcgi-кеш.
К сожалению, многие пользователи начали сообщать о заказах-призраках или захватывать чужие учетные записи (крошечный!!!!). Из-за исчерпывающего копания кажется, что страницы были кэшированы с помощью set-cookie! Таким образом, последующие пользователи, которые не отправляли ранее существующий файл cookie сеанса, получали файл cookie сеанса инициатора кэша. Плохой!
Согласно всей документации, следующие настройки должны предотвратить это (по крайней мере, насколько я понимаю):
fastcgi_pass_header Set-Cookie;
fastcgi_pass_header Cookie;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
Просматривая отдельные кэши, я заметил несколько страниц с set-cookie: [somerandomsessionid] Согласно документации nginx в fastcgi_cache_valid...
Если заголовок содержит поле "Set-Cookie", такой ответ не будет кэширован.
Включая Set-Cookie в fastcgi_ignore_headers, могу ли я сказать, что он должен кэшировать set-cookie? Во многих примерах Set-Cookie является частью аргументов fastcgi_ignore_headers. Или это должно предотвратить обработку Set-Cookie, даже если он явно находится в кэшированных файлах?
Вот соответствующие части моей конфигурации:
местоположение ~ .php$ { ...
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_cache OPENCART;
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
fastcgi_cache_purge $purge_method;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_valid 200 5m;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_pass_header Set-Cookie;
#fastcgi_hide_header Set-Cookie;
fastcgi_pass_header Cookie;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
Мои правила обхода кэша (они называются в /etc/conf.d)...
################## Fast CGI Cache Settings
# if we find a PHP session cookie, let's cache it's contents
map $http_cookie $php_session_cookie {
default "";
~PHPSESSID=(?<sessionkey>[a-zA-Z0-9]+) $sessionkey; # PHP session cookie
}
fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=OPENCART:5m max_size=10000m inactive=15m;
fastcgi_cache_key "$scheme$request_method$host$request_uri$is_mobile$php_session_cookie";
map $request_method $purge_method {
PURGE 1;
default 0;
}
################## Cache Header
add_header X-Cache $upstream_cache_status;
################## Cache Bypass Maps
#Don't cache the following URLs
map $request_uri $no_cache_uri {
default 0;
~*/admin/ 1;
~*/dl/ 1;
}
# ~*/music/mp3_[^/]+/[0-9]+/.+$ 1;
map $query_string $no_cache_query {
default 0;
~*route=module/cart$ 1;
~*route=account/ 1; #exclude account links
~*route=checkout/ 1; #exclude checkout links
~*route=module/founders 1;
~*route=module/cart 1;
~*route=product/product/captcha 1;
~*nocache=1 1; # exclude ajax blocks and provide for manual cache override
}
map $http_cookie $no_cache_cookie {
default 0;
}
map $http_x_requested_with $no_cache_ajax {
default 0;
XMLHttpRequest 1; # Don't cache AJAX
}
map $sent_http_x_no_cache $no_no_cache {
default 0;
on 1; # Don't cache generic header when present and set to "on"
}
## Combine all results to get the cache bypass mapping.
map $no_cache_uri$no_cache_query$no_cache_cookie$no_cache_ajax$no_no_cache $no_cache {
default 1;
00000 0;
}
Настройка сеанса в php.ini
session.auto_start = 1
session.cache_expire = 180
session.cache_limiter = nocache
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_secure = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 3600
session.gc_probability = 0
session.hash_function = "sha256"
session.name = PHPSESSID
session.serialize_handler = php
session.use_cookies = 1
session.use_only_cookies = 1
session.use_strict_mode = 1
session.use_trans_sid = 0
Opencart с использованием session_start() при каждой загрузке страницы, поэтому обход php-сессии по большей части мне не подходит. Если бы был способ предотвратить попадание заголовков Set-Cookie в кеш, это, вероятно, сработало бы для меня.
Может кто-то указать мне верное направление?
2 ответа
Вы также должны проверить, что находится в ваших кэшированных файлах.
Например, у меня было в "Set-Cookie" в некоторых кешированных файлах.
vi /var/www/cache/prod/a/05/9671214cbf3a27f79135a52cbd5b305a
Set-Cookie: Mywebsite=arj4m9egloj9jhrlsps7cu29ec; expires=Fri, 08-Jun-2018 14:39:21 GMT; Max-Age=2592000; path=/
Я удалил все мои кэшированные файлы.
rm -rf /var/www/cache/prod/*
И теперь я проверяю, есть ли новый Set-Cookie в новом кэшированном файле:
grep -rn "Set-Cookie" /var/www/cache/prod/
Лучшее решение, которое я нашел, состоит в том, чтобы в части PHP запретить установку Cookie сеанса, когда страница будет кэшироваться:
if( (strpos($_SERVER['REQUEST_URI'], 'include/php/render') === FALSE) &&
(!isBot()) ) {
// No session Cookie for PHP render Images
// No session Cookie Bots (They create one for each page visisted!)
$session_lifetime = 30*24*3600; //30 days
session_set_cookie_params($session_lifetime,"/");
ini_set('session.gc_maxlifetime', $session_lifetime);
ini_set('session.name', 'Blackart');
session_start();
}
Из коробки nginx не кэширует страницы с заголовком Set-Cookie (что имеет смысл - личные данные!), Если вы не поместите их в fastcgi_ignore_headers
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
Вы сказали nginx игнорировать заголовок Set-Cookie и кэшировать в любом случае.
Но чтобы прояснить ситуацию, я не знаю ваш сервер, но я полагаю, что все ваши динамические страницы отправили куки, чтобы сохранить сеанс.
узнайте, отправляет ли opencart определенный файл cookie, если пользователь вошел в систему, а затем проверьте этот файл cookie.
Другой метод: удалите заголовок CacheControl из ignore_headers и установите правильный заголовок в своем коде. для php
header('Cache-Control: public');
если вы хотите кэшировать страницу