防止伪造cookie的方法

<?php
const COOKIE_ENCRYPTION = 'C*Ul<^`GI%\cT0qAI~NHXu2ebn(9@T|T'; // 定义cookie加密串常量

/**
 * 设置Cookie
 *
 * @param string $name Cookie名称
 * @param string $value Cookie值
 * @return bool 设置Cookie结果
 */
function set_cookie(string $name, string $value): bool
{
    // 明文版
    $cookie1 = setcookie($name, $value);

    // 加密版(name和value都加密)
    $name2 = md5($name . COOKIE_ENCRYPTION);
    $value2 = md5($value . COOKIE_ENCRYPTION);
    $cookie2 = setcookie($name2, $value2);

    return $cookie1 && $cookie2;
}

/**
 * 获取Cookie
 *
 * @param string $name Cookie名称
 * @return string|null Cookie值,若Cookie不存在或Cookie是伪造的则返回null
 */
function get_cookie(string $name): ?string
{
    $value = null;

    $name1 = $name; // 明文版name
    $name2 = md5($name . COOKIE_ENCRYPTION); // 加密版name

    // 必须明文版和密文版同时存在
    if (isset($_COOKIE[$name1], $_COOKIE[$name2])) {
        $value1 = $_COOKIE[$name1]; // 明文版value
        $value2 = $_COOKIE[$name2]; // 加密版value

        // 检查Cookie是否是伪造的
        if (md5($value1 . COOKIE_ENCRYPTION) === $value2) {
            $value = $value1;
        }
    }

    return $value;
}

// 设置cookie
set_cookie('name', '张三');
set_cookie('gender', '男');
set_cookie('age', 18);

// 获取cookie
$name = get_cookie('name');
$gender = get_cookie('gender');
$age = get_cookie('age');
echo "俺叫{$name}{$gender}),今年{$age}岁。"; // 俺叫张三(男),今年18岁。


//========== 总结 ==========//
// 1、如果对安全性有更高的要求可以只保存加密版Cookie到客户端,并且Cookie值使用openssl_*()系列函数进行加解密,
//    但这种方式的缺点是前端无法使用Cookie(因为是后端加密),若能保证Cookie仅限于后端读写则建议使用该方式。

Copyright © 2024 码农人生. All Rights Reserved