Этот подход, очевидно, делает предположения и не является непобедимым. Все вычисления выполняются на клиенте, и сервер выполняет некоторые фоновые проверки, чтобы выяснить, мог ли запрос быть подделан. Как и любой другой подход, основанный на клиентах, он не является детерминированным, но делает его очень сложным для лживого клиента.
Основное предположение состоит в том, что долгоживущие HTTP-соединения намного быстрее для передачи данных, даже незначительные в некоторых случаях в зависимости от контекста приложения. Он используется в большинстве систем онлайн-торговли, так как цены на акции могут меняться несколько раз в течение секунды, и это самый быстрый способ передать текущую цену пользователям. Вы можете прочитать больше о HTTP Streaming или Comet здесь.
Начните с создания полнодуплексного ajax-соединения между клиентом и сервером. На сервере есть выделенная линия для связи с клиентом, и клиент, очевидно, может общаться с сервером. Сервер отправляет головоломку и другие сообщения клиенту по этой выделенной линии. Предполагается, что клиент должен подтвердить получение каждого сообщения на сервер вместе со своей локальной меткой времени.
На сервере генерируйте случайные токены (могут быть просто разными целыми числами) после того, как загадка была отправлена, запишите время, когда был создан каждый токен, и передайте его клиенту. Клиент видит сообщение и должен немедленно ретранслировать этот токен вместе с местным временем получения. Чтобы сделать его непредсказуемым для клиента, генерируйте эти серверные токены с произвольными интервалами, например, между 1
и n
мс.
Клиент может отправлять на сервер три типа сообщений:
PUZZLE_RECEIVED
TOKEN_RECEIVED
PUZZLE_COMPLETED
И два типа сообщений, которые сервер отправляет клиенту:
PUZZLE_SENT
TOKEN_SENT
Там может быть много различий во времени в сообщениях, отправляемых от клиента к серверу, но гораздо меньше в другом направлении (и это очень справедливое предположение, эй - мы должны где-то начать ).
Теперь, когда сервер получает квитанцию на сообщение, которое он отправил, запишите время клиента, содержащееся в этом сообщении. Поскольку токен также был ретранслирован обратно в этом сообщении, мы можем сопоставить его с соответствующим токеном на сервере. В конце головоломки клиент отправляет на сервер сообщение PUZZLE_COMPLETED
с местным временем. Время завершения головоломки будет:
PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time
Затем дважды проверьте, рассчитав разницу во времени для каждого отправленного и полученного сообщения.
PUZZLE_RECEIVED.time - PUZZLE_SENT.time
TOKEN_RECEIVED.time - TOKEN_SENT.time
Высокая дисперсия в эти времена подразумевает, что ответ мог быть подделан. Помимо простой дисперсии, есть много статистического анализа, который вы можете сделать на этих данных, чтобы найти странные шаблоны.