Я строю систему, в которой мне нужно назначить пользователям доступ к определенному (индивидуальному) числу активов. Эти активы (потенциально насчитывающие десятки тысяч).
Я думал сделать это с побитовыми сравнениями, поэтому что-то вроде хранения значения 3, если пользователь имеет доступ к активам 1 и 2, значение 7 для доступа к 1, 2 и 3 и т. Д. И т. Д.
Доступ не обязательно последователен, поэтому пользователь может легко получить доступ к активам 10, 12 и 24324.
Я быстро столкнулся с проблемой, используя биты, где сервер не собирал активы за 63-й бит, поэтому, очевидно, я либо неправильно понял, либо биты – это тупой способ сохранить такую информацию.
Мой код, работающий на 64-битной системе Linux, – это (просто для тестирования, очевидно, чтобы обнаружить такие ограничения, как это):
<?php $bitwise = $_GET['bitwise']; if (isset($bitwise)) { echo "<br/>bitwise input: "; echo $bitwise; $bitcount = 0; for ($i=1;$i<=$bitwise;$i*=2) { if (($i & $bitwise) > 0) { $bitcount++; echo "<br/>{$bitcount}: " . $i . " is in " . $bitwise; } } }
?>
И я вводил тестовые значения через запрос. Однако, независимо от того, какое значение я вводил, максимальный счет, который я могу получить, равен 63.
Итак, мой вопрос: это просто потому, что я использую побитовые сравнения для чего-то, что они не идеальны для (моей теории), или моя реализация этого просто неверна?
Следующим моим решением было бы сохранить «бит» в массивах, поэтому, если у кого-то есть доступ к активам 1, 2 и 3, я буду хранить их список как [1,2,3]. Вряд ли кто-то имеет доступ к более чем, скажем, сотне конкретных активов. Это разумный способ сделать это? Я понимаю, что этот вопрос ставит вопрос в дискуссионно-достойную территорию, но, надеюсь, он все еще достаточно конкретный.
Разумеется, проблемы Paramount – это производительность, если сервер должен одновременно обслуживать большое количество клиентов.
(пожалуйста, извините неправильную терминологию, где это применимо, надеюсь, мой смысл ясен).
Это стандартное поведение – на 64-битном скомпилированном PHP целые числа имеют максимальную длину 64 бит. Хотя это согревает мое секретное серое сердце бороды, если у вас более 64 разных ролей, побитовое решение является неправильным для контроля доступа.
Еще две вещи, о которых стоит упомянуть.
Во-первых, делать это по соображениям производительности, вероятно, является преждевременной оптимизацией для веб-приложения. Поиск ACL не будет узким местом в вашей системе в течение длительного времени, если вообще. Кроме того, неясно, обеспечивают ли побитовые операторы такое преимущество производительности PHP, учитывая динамический характер языка.
Во-вторых, причина, по которой вы ограничены 63 битами, заключается в том, что PHP (кажется?) Использует комплимент Two для их реализации целых чисел со знаком. Конечный бит предназначен для представления положительных или отрицательных чисел. Я задал этот вопрос о побитом NOT
некоторое время назад, поэтому этот вопрос привлек мое внимание.