Добавление защищенного атрибута в куки Woocommerce

Я пытаюсь привести наш сервер в соответствие с PCI и перейти к последней проблеме настройки безопасности файлов cookie Woocommerce. Я использую все текущие версии Wordpress/Woocommerce, и на сервере работает 100% SSL/HTTPS по всему сайту.

Файлы cookie, которые я пытаюсь обезопасить: woocommerce_recently_viewed

Я попробовал следующее без удачи:

Добавлен в мой файл функций:

add_filter( 'wc_session_use_secure_cookie', '__return_true' );

Добавлено в index.php:

@ini_set('session.cookie_httponly', 'On');
@ini_set('session.cookie_secure', 'On');
@ini_set('session.use_only_cookies', 'On');

Добавлено в php.ini:

session.cookie_httponly = 1
session.cookie_secure = 1
session.use_only_cookies = 1

Мое последнее средство - настроить конфигурацию сервера (я использую Nginx), НО лучше бы решить эту проблему на уровне приложения. Любая помощь в этом вопросе будет признательна.

1 ответ

Решение

Перво-наперво: woocommerce_recently_viewed не является сессионным cookie в смысле PHP. Это обычный файл cookie, созданный с setcookie PHP функция

Это означает, что ни ini_set ни wc_session_use_secure_cookie изменит это поведение.

Я скачал исходный код WooCommerce и нашел woocommerce\includes\wc-product-functions.php:

/**
 * Track product views.
 */
function wc_track_product_view() {
    if ( ! is_singular( 'product' ) || ! is_active_widget( false, false, 'woocommerce_recently_viewed_products', true ) ) {
        return;
    }

    global $post;

    if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) )
        $viewed_products = array();
    else
        $viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] );

    if ( ! in_array( $post->ID, $viewed_products ) ) {
        $viewed_products[] = $post->ID;
    }

    if ( sizeof( $viewed_products ) > 15 ) {
        array_shift( $viewed_products );
    }

    // Store for session only
    wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
}

add_action( 'template_redirect', 'wc_track_product_view', 20 );

wc_setcookie определяется следующим образом (woocommerce\includes\wc-core-functions.php):

/**
 * Set a cookie - wrapper for setcookie using WP constants.
 *
 * @param  string  $name   Name of the cookie being set.
 * @param  string  $value  Value of the cookie.
 * @param  integer $expire Expiry of the cookie.
 * @param  string  $secure Whether the cookie should be served only over https.
 */
function wc_setcookie( $name, $value, $expire = 0, $secure = false ) {
    if ( ! headers_sent() ) {
        setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure );
    } elseif ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        headers_sent( $file, $line );
        trigger_error( "{$name} cookie cannot be set - headers already sent by {$file} on line {$line}", E_USER_NOTICE );
    }
}

Как вы можете видеть, нет никакого фильтра WordPress, к которому можно было бы подключиться (это действительно должна быть настройка, задайте запрос функции!), Поэтому вам нужно добавить $secure параметр к источникам woocommerce...

... но есть и другой способ (вроде обезьяньего патча, но эй, по крайней мере мы не разбиваем вещи через обновления):

function custom_wc_track_product_view() {
    if ( ! is_singular( 'product' ) || ! is_active_widget( false, false, 'woocommerce_recently_viewed_products', true ) ) {
        return;
    }

    global $post;

    if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) )
        $viewed_products = array();
    else
        $viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] );

    if ( ! in_array( $post->ID, $viewed_products ) ) {
        $viewed_products[] = $post->ID;
    }

    if ( sizeof( $viewed_products ) > 15 ) {
        array_shift( $viewed_products );
    }

    // Store for session only
    wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ), 0, true );
}

remove_action( 'template_redirect', 'wc_track_product_view', 20 );
add_action( 'template_redirect', 'custom_wc_track_product_view', 20 );

Я скопировал функцию с другим именем, сделал необходимые изменения, а затем заменил оригинальный хук своим. Поместите этот код в новый плагин или в тему functions.php,

К сожалению, нет лучшего способа без сотрудничества с WooCommerce.

Другие вопросы по тегам