«JWT», схема входа в систему аутентификации, которую вы должны понимать

Java
«JWT», схема входа в систему аутентификации, которую вы должны понимать

** Я Воздушный змей, публичный номер «Воздушный змей в древние времена», вдохновитель программистов с глубиной и широтой, а также пастырский фермер, занимающийся кодом, который планировал писать стихи, но написал код!

Статья будет включена вJavaNewBeeТакже есть карта знаний Java back-end, и в ней путь от Xiaobai до Daniel. **

Полное название JWT — JSON Web Token, это очень популярное решение для междоменной аутентификации, которое часто используется в сценариях единого входа.

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

Почему это?

традиционный метод аутентификации

Начните со сценария входа

Вы использовали так много веб-сайтов и приложений, и многие из них требуют входа в систему, поэтому давайте выберем сцену и поговорим о ней.

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

Для тех веб-сайтов или приложений, которые часто используются, обычно не требуется вводить пароль в течение длительного времени, чтобы после смены компьютера или мобильного телефона вы не могли вспомнить пароли некоторых часто используемых веб-сайтов или приложений. . . .

Ранние методы аутентификации сеанса cookie

В первые дни в Интернете доминировала сеть, а клиентом был браузер, поэтому метод Cookie-Session был наиболее часто используемым методом аутентификации в первые дни.До сих пор некоторые веб-сайты все еще используют этот метод для аутентификации. .

Процесс сертификации примерно выглядит следующим образом:

  1. Пользователь вводит имя пользователя, пароль или авторизуется в системе с помощью проверочного кода SMS;
  2. После проверки на стороне службы создается информация о сеансе и для сохранения файла cookie SessionID отправляется обратно в браузер;
  3. В следующий раз, когда клиент инициирует запрос, он автоматически предоставит информацию о куки, и сервер получит информацию о сеансе через куки для проверки;

image-20200706173031724

Но почему это традиционные методы аутентификации, потому что теперь у всех есть смартфон, у многих людей нет компьютеров, я обычно использую различные приложения на телефоне, такие как Taobao, много драк и так далее. В связи с этой тенденцией традиционные сеансы cookie столкнулись с некоторыми проблемами: 1, во-первых, сеанс cookie можно использовать только в веб-сценарии, если это приложение, приложение не может быть местом для хранения файлов cookie. Продукты теперь в основном одновременно предоставляют веб-конец и приложение, используемое двумя способами, даже просто небольшое приложение продукта.

2. Вернитесь на десять тысяч шагов назад и скажите, что ваш продукт поддерживает только Интернет, и вы также должны учитывать междоменные проблемы, но файлы cookie не могут быть междоменными. Возьмем, к примеру, Tmall Mall: при входе в Tmall Mall вверху вы увидите такие меню, как Tmall Supermarket, Tmall International и Tmall Members. При нажатии на эти меню будут вводиться разные доменные имена, и файлы cookie для разных доменных имен будут разными.Вы не можете получить файл cookie доменного имени B для доменного имени A, даже если это субдомен.

image-20200706173939291

3. Если это распределенный сервис, необходимо рассмотреть вопрос синхронизации сеансов. Современные веб-сайты и приложения в Интернете в основном представляют собой распределенные развертывания, то есть на стороне сервера находится более одной машины. Когда пользователь выполняет операцию входа на страницу, действие входа должно быть запрошено на одном из серверов. Ваша идентификационная информация должна быть сохранена.Традиционным способом является сохранение сеанса.

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

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

4, куки. Существует риск CSRF (подделка запроса между станциями). Межстанционный запрос на подделку — это метод атаки, который выполняет неконтентную операцию в зарегистрированном в данный момент веб-приложении. CSRF использует доверие веб-сайта к веб-браузеру пользователя. Проще говоря, злоумышленник обманывает браузер пользователя, чтобы он зашел на сертифицированный веб-сайт и выполнил некоторые операции (например, покупку товаров). Поскольку браузер прошел сертификацию, посещаемый веб-сайт будет считаться инициированным активным пользователем. Например, я хакер, я нашел CSRF-уязвимость на техническом веб-сайте, который вы часто посещаете. Публикация статьи поддерживает формат HTML, а затем добавить опасный контент в HTML, например

 <img src="http://www.examplebank.com/withdraw?account=Alice&amount=1000&for=Badman">

Src указывает на то, что этот адрес является тем, который вы обычно используете для оплаты на сайте магазина (конечно, это только пример, реальная атака может быть не такой простой), и если вы ранее подписали файл cookie, идентифицирующий вашу личность, он был сохранен. Когда вы почистите статью, я разместил время, тег img загрузится, это сработает CSRF-атака, оплата на этом сайте без вашего ведома.

Модернизация сеанса cookie

Поскольку с традиционной аутентификацией Cookie-Session возникает много проблем, приведенную выше схему можно преобразовать. 1. Преобразование файлов cookie Поскольку файлы cookie нельзя использовать в небраузерных приложениях, таких как APP, они не используются для хранения на стороне клиента, а вместо этого используются другие методы. Поменять на что? Локальное хранилище можно использовать в Интернете, а клиентскую базу данных можно использовать в приложении, что позволяет достичь междоменного доступа и избежать CSRF.

2. На сервере нет сеанса, а информация о сеансе извлекается и хранится в базе данных в памяти, такой как Redis, что не только повышает скорость, но и позволяет избежать проблемы синхронизации сеанса;

После преобразования процесс сертификации стал следующим:

  1. Пользователь вводит имя пользователя, пароль или авторизуется в системе с помощью проверочного кода SMS;
  2. После проверки сервера структура данных, созданная на основе информации об аутентификации, сохраняется в Redis, а значение ключа возвращается клиенту;
  3. Клиент получает возвращенный ключ и сохраняет его в локальном хранилище или в локальной базе данных;
  4. В следующий раз, когда клиент запросит снова, добавьте значение ключа в заголовок или тело запроса;
  5. Сервер получает аутентификационную информацию от Redis по полученному ключу;

На следующих двух рисунках показан процесс первого и не первого входа в систему соответственно.

首次登录

非首次登录

После жесткой трансформации проблемы, существующие в традиционном методе Cookie-Session, были решены. Эту трансформацию должны сделать сами разработчики в проекте. Модернизация, безусловно, требует много времени и труда, и могут быть лазейки.

Внешний вид JWT

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

Если вы новичок в JWT, наиболее сомнительным может быть: почему JWT может полностью полагаться на клиента (например, браузер) для реализации функции аутентификации, а вся информация аутентификации хранится на клиенте Как обеспечить безопасность?

Структура данных JWT

Окончательная форма JWT — это строка, состоящая изголова,нагрузкаиподписатьЭти три части состоят из "."разошлись. Как следующее:

997EDE1C-5689-4C3F-98E8-25C25BBEC3FC

голова

Заголовок выражается в формате JSON и используется для указания типа токена и алгоритма шифрования. Форма выглядит следующим образом, что указывает на то, что используется формат JWT, а алгоритм шифрования — HS256, который является наиболее часто используемым алгоритмом, и есть много других.

{
  "alg": "HS256",
  "typ": "JWT"
}

В соответствии с красной частью заголовка на приведенном выше рисунке требуется кодировка Base64.

нагрузка

Он используется для хранения данных, требуемых сервером, таким как пользовательская информация, такая как имя, пол, возраст и т. Д. Следует отметить, что лучше не ставить важную конфиденциальную информацию, такую ​​как пароли.

{
  "name": "古时的风筝",
  "introduce": "英俊潇洒"
}

Кроме того, JWT также указывает 7 полей для выбора разработчиками.

  • iss (эмитент): Эмитент
  • exp (время истечения): время истечения
  • суб (тема): тема
  • aud (аудитория): аудитория
  • nbf (не раньше): время действия
  • IAT (выдан AT): вопрос времени
  • jti (идентификатор JWT): число

Эта часть информации также закодирована в Base64.

подписать

В подписи есть формула расчета.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  Secret
)

использоватьHMACSHA256Алгоритм вычисляет, что этот метод имеет два параметра. Первый параметр (заголовок в кодировке base64 + полезная нагрузка в кодировке base64), соединенный точками, а последний параметр — это настраиваемый строковый ключ. Ключ не должен отображаться в клиенте, сервер должен знать об этом.

Как пользоваться

После понимания структуры и алгоритма JWT, как его использовать? Предположим, у меня есть веб-сайт здесь.

1. Когда пользователь входит на веб-сайт, ему необходимо ввести имя пользователя, пароль или способ подтверждения по SMS для входа в систему. Когда на сервер поступает запрос на вход, сервер проверяет учетную запись и пароль, а затем вычисляет строку JWT. и возвращает его клиенту.

2. После того, как клиент получит строку JWT, он сохранит ее в файле cookie или в LocalStorage браузера.

3. Отправьте запрос еще раз, например, при запросе страницы настроек пользователя добавьте строку JWT в заголовок HTTP-запроса или напрямую поместите ее в тело запроса.

4. После того, как сервер получит строку JWT, он использует заголовок base64 и полезную нагрузку base64 для передачиHMACSHA256Алгоритм вычисляет раздел подписи, который сравнивает результат расчета и полученный раздел знака, если он согласован, запрос не является проблематичным, если он несовместим, срок действия запроса истек или незаконные запросы.

как обеспечить безопасность

Ключом к обеспечению безопасности являетсяHMACSHA256Или алгоритм шифрования того же типа, потому что процесс шифрования необратим, поэтому информация о ключе не может быть расшифрована в соответствии с JWT, переданным на внешний интерфейс.

Кроме того, подписи, полученные после шифрования разных заголовков и полезной нагрузки, отличаются, поэтому, если кто-то изменит информацию в части полезной нагрузки, окончательный зашифрованный результат обязательно будет отличаться от того, что было до изменения, поэтому последний проверенный результат является недопустимым запросом.

Безопасно ли для других получать полную версию JWT?

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

Тогда, если грабитель не изменит его после получения и использует его напрямую, нет никакого способа Чтобы предотвратить кражу грабителем в большей степени, следует использовать протокол HTTPS вместо протокола HTTP, который может эффективно предотвратить некоторые промежуточные атаки угона.

Некоторые студенты должны сказать, это не безопасно, заставить строки JWT легко моделировать запрос. Это действительно это, но предпосылка такое, как вы можете получить его, в дополнение к средней угнему выше, есть ли способ?

Если грабитель не захватит ваш компьютер напрямую, в этом случае, извините, небезопасен не только JWT, но и любой другой веб-сайт или любой метод аутентификации.

Хотя такие случаи редки, при использовании JWT все же следует обращать внимание на то, чтобы время экспирации устанавливалось разумно, не слишком долго.

один вопрос

Проблема с JWT, из-за которой многие команды разработчиков отказались от его использования, заключается в том, что после выпуска токена JWT сервер не может его сбросить, если только не истечет срок его действия. Есть много приложений, которые позволяют по умолчанию использовать только последний клиент входа в систему и не разрешают несколько входов в систему. JWT не может этого сделать, потому что выдается новый токен, но старый токен все еще доступен до истечения срока его действия. В этом случае серверу необходимо добавить соответствующую логику.

Общие библиотеки JWT

На официальном сайте JWT перечислены библиотеки, соответствующие различным языкам, среди которых следующая Java.

image-20200817112359199

отjava-jwtНапример.

1. Импортируйте соответствующий пакет Maven.

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

2. При входе позвонитеcreateМетод получает токен и возвращает его во внешний интерфейс.

public static String create(){
  try {
    Algorithm algorithm = Algorithm.HMAC256("secret");
    String token = JWT.create()
      .withIssuer("auth0")
      .withSubject("subject")
      .withClaim("name","古时的风筝")
      .withClaim("introduce","英俊潇洒")
      .sign(algorithm);
    System.out.println(token);
    return token;
  } catch (JWTCreationException exception){
    //Invalid Signing configuration / Couldn't convert Claims.
    throw exception;
  }
}

3. После успешного входа в систему токен помещается в заголовок или тело запроса, когда запрос инициируется снова, и сервер проверяет токен.

public static Boolean verify(String token){
  try {
    Algorithm algorithm = Algorithm.HMAC256("secret");
    JWTVerifier verifier = JWT.require(algorithm)
      .withIssuer("auth0")
      .build(); //Reusable verifier instance
    DecodedJWT jwt = verifier.verify(token);
    String payload = jwt.getPayload();
    String name = jwt.getClaim("name").asString();
    String introduce = jwt.getClaim("introduce").asString();
    System.out.println(payload);
    System.out.println(name);
    System.out.println(introduce);
    return true;
  } catch (JWTVerificationException exception){
    //Invalid signature/claims
    return false;
  }
}

4. Используйте метод create для создания токена и проверки его с помощью метода verify.

public static void main(String[] args){
  String token = create();
  Boolean result = verify(token);
  System.out.println(result);
}

Следующие результаты

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaW50cm9kdWNlIjoi6Iux5L-K5r2H5rSSIiwiaXNzIjoiYXV0aDAiLCJuYW1lIjoi5Y-k5pe255qE6aOO562dIn0.ooQ1K_XyljjHf34Nv5iJvg1MQgVe6jlphxv4eeFt8pA
eyJzdWIiOiJzdWJqZWN0IiwiaW50cm9kdWNlIjoi6Iux5L-K5r2H5rSSIiwiaXNzIjoiYXV0aDAiLCJuYW1lIjoi5Y-k5pe255qE6aOO562dIn0
古时的风筝
英俊潇洒
true

Струны JWT, созданные с методом создания, могут пройти проверку.

И если я изменю часть полезной нагрузки строки JWT, часть между двумя точками, а затем вызову метод проверки для проверки, она появитсяJWTVerificationExceptionИсключение, не удалось пройти проверку.

Если этот красивый молодой человек считает, что это неплохо, не забудьте поставить лайк!

Публичный аккаунт "Древний коршун", Добро пожаловать в поиск и подписку WeChat, давайте вместе станем лучше!

Разработчик Java, инженер полного стека, убийца ошибок, хорошо решаю проблемы.

Придерживайтесь оригинального выхода галантереи, вы можете подписаться на меня сейчас или посмотреть исторические статьи, а затем обратить внимание.