Статьи

SecureLogin для веб-приложений Java

Нет, в заголовке нет пропущенных пробелов. Речь идет не о безопасном входе в систему, а о протоколе SecureLogin, разработанном Егором Хомаковым , консультантом по безопасности, который прославился тем, что взял на себя обязательство осваивать проект Rails без разрешения.

Протокол SecureLogin очень интересен, поскольку он не зависит от какой-либо центральной стороны (например, поставщиков OAuth, таких как Facebook и Twitter), что позволяет избежать всех ошибок OAuth (которые Хомаков часто критиковал). Это также не менеджер паролей. Это просто программное обеспечение на стороне клиента, которое выполняет немного крипто, чтобы доказать серверу, что это действительно правильный пользователь. Чтобы это работало, две части являются ключевыми:

  • Использование мастер-пароля для генерации закрытого ключа. Он использует функцию получения ключа, которая гарантирует, что созданный закрытый ключ обладает достаточной энтропией. Таким образом, используя один и тот же главный пароль и один и тот же адрес электронной почты, вы будете получать один и тот же закрытый ключ при каждом использовании пароля и, следовательно, один и тот же открытый ключ. И вы единственный, кто может доказать, что этот открытый ключ принадлежит вам, подписав сообщение своим закрытым ключом.
  • Поставщики услуг (веб-сайты) идентифицируют вас по вашему открытому ключу, сохраняя его в базе данных при регистрации, а затем просматривая его при каждом последующем входе в систему.

Клиентская часть в идеале выполняется собственным клиентом — плагином для браузера (один доступен для Chrome) или приложением для ОС (включая мобильные). Это может показаться утомительным, но на самом деле это быстро и просто, и это одноразовое мероприятие (и это проще, чем менеджеров паролей).

Я должен признать — мне это нравится, потому что у меня уже была похожая идея. В моей презентации «биометрической идентификации» (где я обсуждаю ловушки использования схем идентификации только по биометрии) я предложил (слайд 23) схему идентификации, которая использует биометрию (например, сканированную с помощью вашего телефона) + пароль для создания закрытого ключа ( используя функцию получения ключа). И биометрические данные могут быть легко добавлены в SecureLogin в будущем.

Конечно, это не все розы, так как одна проблема еще не полностью решена — отзыв. В случае, если кто-то украдет ваш главный пароль (или вы подозреваете, что он может быть украден), вы можете изменить его и уведомить всех поставщиков услуг об этом изменении, чтобы они могли заменить ваш старый открытый ключ новым. Это имеет два значения: во-первых, у вас может не быть полного списка сайтов, на которых вы зарегистрированы, и, поскольку вы могли сменить устройство или использовать несколько устройств, могут быть сайты, которые никогда не узнают об изменении вашего пароля. Существуют предлагаемые решения ( пункты 3 и 4 ), но они не являются неотъемлемой частью протокола и зависят от централизованных служб. Вторая проблема — что если злоумышленник сначала поменяет ваш пароль? Чтобы предотвратить это, поставщики услуг, вероятно, должны полагаться на проверку электронной почты, которая не является ни частью протокола, ни поощряется им. Но вам, возможно, придется сделать это в любом случае, в качестве гарантии.

Хомаков не только определил протокол, но и предоставил реализации нативных клиентов, так что любой может начать его использовать. Поэтому я решил добавить его в проект, над которым я сейчас работаю ( страница входа здесь ). Для этого мне понадобилась Java-реализация проверки сервера, и, поскольку такой реализации не было (пока предоставляются только ruby ​​и node.js), я реализовал ее сам . Поэтому, если вы собираетесь использовать SecureLogin с веб-приложением Java, вы можете использовать его вместо развертывания собственного. При его реализации я столкнулся с несколькими незначительными проблемами, которые могут привести к изменениям протокола, поэтому я предполагаю, что обратная совместимость также должна быть как-то включена в протокол (через управление версиями).

Итак, как выглядит код? На стороне клиента у вас есть кнопка и небольшой JavaScript:

1
2
3
4
5
<!-- get the latest sdk.js from the GitHub repo of securelogin
   or include it from https://securelogin.pw/sdk.js -->
<script src="js/securelogin/sdk.js"></script>
....
<p class="slbutton" id="securelogin">⚡ SecureLogin</p>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
$("#securelogin").click(function() {
  SecureLogin(function(sltoken){
    // TODO: consider adding csrf protection as in the demo applications
        // Note - pass as request body, not as param, as the token relies
        // on url-encoding which some frameworks mess with
    $.post('/app/user/securelogin', sltoken, function(result) {
            if(result == 'ok') {
         window.location = "/app/";
            } else {
                 $.notify("Login failed, try again later", "error");
            }
    });
  });
  return false;
});

Одна кнопка может быть использована как для входа в систему, так и для регистрации, или вы можете иметь отдельную форму регистрации, если она должна содержать дополнительные сведения, а не только электронную почту. Поскольку я добавил SecureLogin в дополнение к своему логину на основе пароля, я сохранил две формы.

На сервере вы просто делаете следующее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
@RequestMapping(value = "/securelogin/register", method = RequestMethod.POST)
@ResponseBody
public String secureloginRegister(@RequestBody String token, HttpServletResponse response) {
    try {
        SecureLogin login = SecureLogin.verify(request.getSecureLoginToken(), Options.create(websiteRootUrl));
        UserDetails details = userService.getUserDetailsByEmail(login.getEmail());
        if (details == null || !login.getRawPublicKey().equals(details.getSecureLoginPublicKey())) {
            return "failure";
        }
        // sets the proper cookies to the response
        TokenAuthenticationService.addAuthentication(response, login.getEmail(), secure));
        return "ok";
    } catch (SecureLoginVerificationException e) {
        return "failure";
    }
}

Это spring-mvc, но это может быть любой веб-фреймворк. Вы также можете как-то включить это в поток безопасности пружины. Мне никогда не нравилась сложность Spring-Security, поэтому я сделал это вручную. Кроме того, вместо строк вы можете возвращать правильные коды состояния. Обратите внимание, что я делаю поиск по электронной почте и только потом проверяю открытый ключ (как будто это пароль). Вы можете сделать наоборот, если у вас есть правильный индекс в столбце открытого ключа.

Я бы не советовал использовать систему только с SecureLogin, так как проект все еще находится на ранней стадии, и пользователи могут не чувствовать себя комфортно с ним. Но, конечно, добавить его в качестве опции — хорошая идея.

Опубликовано на Java Code Geeks с разрешения Божидара Божанова, партнера нашей программы JCG . См. Оригинальную статью здесь: SecureLogin для веб-приложений Java

Мнения, высказанные участниками Java Code Geeks, являются их собственными.