什么时候应该启用服务器端会话而不是客户端会话?
我想不出除了“用户体验”之外您还想要客户端的情况。
会话标识符应始终位于服务器端,因为服务器应验证会话是否有效。
将 CSRF 令牌放在客户端 cookie 中是否安全,无论它是否加密?
反 CSRF 令牌应该包含随机生成的数据,这比生成加密字符串“便宜”得多,只要字符串足够长且足够随机。
我认为将反 CSRF 令牌存储在 cookie 中是不够的。
我建议创建一个系统,其中从隐藏的输入字段提交反 CSRF 令牌并在标头中传输。两者都应该在服务器端进行检查。
这是 PHP 中的一个示例:
function generateToken($key) {
$token = base64_encode(openssl_random_pseudo_bytes(16));
$_SESSION['csrf_' . $key] = $token;
return $token;
}
function checkToken($key, $value) {
if (!isset($_SESSION['csrf_' . $key]))
return false;
if (!$value)
return false;
if ($_SESSION['csrf_' . $key] !== $value)
return false;
unset($_SESSION['csrf_' . $key]);
return true;
}
if ($_POST and $_POST['action'] == "something")
{
$header_token = apache_request_headers()['X-Anti-Csrf-Token'];
$post_token = $_POST['token'];
$post_token = str_replace(" ", "+", $post_token);
if ($header_token == $post_token)
{
if (checkToken('settings', $post_token))
{
// ok; do something
}
}
else
{
// wrong; do something
}
}
在处理之前发送标头:
<script>
$("#some_div").submit(function(event) {
event.preventDefault();
var $form = $(this),
url = $form.attr('action');
var posting = $.ajax(url, {
type: 'POST',
processData: true,
dataType: "text",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-Anti-CSRF-Token', $('#token').val());
}
这段代码将生成令牌并将其放入隐藏的输入字段中。
<input id="token" type="hidden" value="<?php echo generateToken('settings'); ?>">