Если ваш веб-хостинг позволяет это или вам нужно будет иметь дело с конфиденциальными данными, используйте HTTPS, точка. (Часто этого требует закон афаик).
В противном случае, если вы хотите что-то сделать через HTTP. Я бы сделал что-то подобное.
- Сервер встраивает свой открытый ключ на страницу входа.
- Клиент заполняет форму входа и нажимает "Отправить".
- Запрос AJAX получает текущую метку времени с сервера.
- Сценарий на стороне клиента объединяет учетные данные, метку времени и соль (хешированные из аналоговых данных, например, движения мыши, события нажатия клавиш), шифрует их с помощью открытого ключа.
- Отправляет полученный хеш.
- Сервер расшифровывает хеш
- Проверяет, достаточно ли недавняя временная метка (допускает только короткое 5-10 секундное окно). Отклоняет логин, если отметка времени слишком старая.
- Хранит хеш в течение 20 секунд. Отклоняет один и тот же хеш для входа в систему в течение этого интервала.
- Аутентифицирует пользователя.
Таким образом, пароль защищен, и тот же хэш аутентификации не может быть воспроизведен.
О безопасности токена сеанса. Это немного сложнее. Но можно немного усложнить повторное использование украденного токена сеанса.
- Сервер устанавливает дополнительный файл cookie сеанса, который содержит случайную строку.
- Браузер отправляет этот файл cookie при следующем запросе.
- Сервер проверяет значение в файле cookie, если оно отличается, то он уничтожает сеанс, в противном случае все в порядке.
- Сервер снова устанавливает cookie с другим текстом.
Таким образом, если токен сеанса был украден и запрос был отправлен кем-то другим, то при следующем запросе исходного пользователя сеанс будет уничтожен. Так что, если пользователь активно просматривает сайт, часто нажимая на ссылки, то вор не уйдет далеко с украденным токеном. Эту схему можно усилить, потребовав другой аутентификации для конфиденциальных операций (например, удаления учетной записи).
РЕДАКТИРОВАТЬ: обратите внимание, что это не предотвращает атаки MITM, если злоумышленник настраивает свою собственную страницу с другим открытым ключом и отправляет запросы прокси на сервер. Для защиты от этого открытый ключ должен быть закреплен в локальном хранилище браузера или в приложении для обнаружения подобных уловок.
О реализации: RSA, вероятно, является наиболее известным алгоритмом, но он довольно медленный для длинных ключей. Я не знаю, насколько быстрой будет реализация PHP или Javascript. Но, наверное, есть более быстрые алгоритмы.