Недавно я переключил экземпляр opencart с Apache + mod_php на nginx + fastcgi + php-fpm. Я пытался использовать кеширование для большинства страниц через fastcgi-cache.
К сожалению, многие пользователи начали сообщать о заказах-призраках или захвате чужих учетных записей (уууу !!!!). После тщательного рытья оказалось, что страницы были кэшированы с помощью 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, даже если он явно находится в кешированных файлах?
Вот соответствующие части моей конфигурации:
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;
################## 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;
}
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 в кеш, это, вероятно, сработало бы для меня.
Может кто-то указать мне верное направление?
Из коробки nginx не кэширует страницы с заголовком Set-Cookie (что имеет смысл - личные данные!), Если вы не поместите его в fastcgi_ignore_headers
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
вы сказали nginx в любом случае игнорировать заголовок Set-Cookie и кешировать.
Но чтобы прояснить, я не знаю ваш сервер, но я предполагаю, что все ваши динамические страницы отправили cookie для сохранения сеанса.
узнайте, отправляет ли opencart определенный файл cookie, если пользователь вошел в систему, затем проверьте этот файл cookie.
Другой метод: удалите заголовок CacheControl из ignore_headers и установите правильный заголовок в коде. для php
header('Cache-Control: public');
если вы хотите кешировать страницу
Вы также должны проверить, что находится в ваших кешированных файлах.
Например, у меня был "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();
}