Веб-токен JSON Даrfc7519Стандарт, который использует JSON для передачи данных, чтобы определить, вошел ли пользователь в систему.
До jwt сеанс использовался для аутентификации пользователя.
Следующий код написан на javascript.
Смотрите оригинальную ссылкуБлог Ямадзуки
session
Традиционный способ входа — использоватьsession + token
.
token
Относится к использованию токенов на стороне клиента в качестве учетных данных статуса пользователя, которые обычно хранятся в браузере.localStorage
илиcookie
середина.
session
Это относится к использованию базы данных redis или sql на стороне сервера для хранения парных отношений ключ-значение user_id и токена.Основной принцип работы заключается в следующем.
const sessions = {
"ABCED1": 10086,
"CDEFA0": 10010
}
// 通过 token 获取 user_id, 完成认证过程
function getUserIdByToken (token) {
return sessions[token]
}
если хранится вcookie
часто можно услышать вsession + cookie
схема входа. На самом деле хранится вcookie
,localStorage
четноеIndexedDB
илиWebSQL
Каждый из них имеет свои преимущества и недостатки, и основная идея одна и та же.
оcookie
а такжеtoken
достоинства и недостатки, вtoken authetication vs cookiesЕсть обсуждения.
Если вы не используете файлы cookie, вы можете воспользоватьсяlocalStorage + Authorization
способ аутентификации.
// http 的头,每次请求权限接口时,需要携带 Authorization Header
const headers = {
Authorization: `Bearer ${localStorage.get('token')}`
}
порекомендовать библиотекуlocalForage,использовать
IndexedDB
,WebSQL
а такжеIndexedDB
Сделайте хранилище ключ-значение.
логин без гражданства
session
Необходимо хранить соответствующую информацию о пользователях и токенах в базе данных, поэтому она называетсясостояние.
Только представьте, как вы можете войти в систему, не сохраняя состояние пользователя в базе данных.
первый метод:Внешний интерфейс напрямую передает user_id на сервер
Недостаток также особенно очевиден: пользователь может легко вмешаться в задачу user_id, а настройка разрешений бесполезна. Но мысль правильная, а то вниз.
Улучшать:Симметрично зашифровать user_id
Чуть сильнее, чем выше, если предыдущий метод представляет собой пустое окно, этот метод представляет собой окно, вклеенное бумагой.
Улучшать:User_id не нужно шифровать, нужно только подписать, чтобы гарантировать, что он не будет подделан
В этом и заключается идея jwt, user_id, алгоритма шифрования и подписи, которые хранятся у клиента вместе, и каждый раз, когда запрашивается интерфейс, сервер оценивает согласованность подписи.
Json Web Token
просто поHeader
,Payload
а такжеSignature
Зависит от.
сшиты вместе.
Header
Заголовок состоит из следующих алгоритмов и типов асимметричного шифрования.
const header = {
// 加密算法
alg: 'HS256',
type: 'jwt'
}
Payload
Полезная нагрузка поRegistered Claimи состав данных, которые необходимо передать. Эти поля данных также называютсяClaim
.
Registered Claim
более важно"exp" Claim
Указывает время истечения срока действия, которое будет установлено при входе пользователя в систему.
const payload = {
// 表示 jwt 创建时间
iat: 1532135735,
// 表示 jwt 过期时间
exp: 1532136735,
// 用户 id,用以通信
user_id: 10086
}
Signature
ВойтиHeader
,Payload
а такжеsecretOrPrivateKey
вычислено.
заsecretOrPrivateKey
, если алгоритм шифрования используетHMAC
, то строка, еслиRSA
илиECDSA
, это PrivateKey.
// 由 HMACSHA256 算法进行签名,secret 不能外泄
const sign = HMACSHA256(base64.encode(header) + '.' + base64.encode(payload), secret)
// jwt 由三部分拼接而成
const jwt = base64.encode(header) + '.' + base64.encode(payload) + '.' + sign
Из сгенерированных правил jwt мы знаем, что клиент может анализировать полезную нагрузку, поэтому не переносите в полезную нагрузку конфиденциальные данные, такие как пароли пользователей.
чек
В правиле генерации видно, что первые две части jwt представляют собой кодировку base64 заголовка и полезной нагрузки.
Когда сервер получает токен клиента, он анализирует первые две части, чтобы получить заголовок и полезные данные, и использует алгоритм в заголовке для подписи с помощью secretOrPrivateKey, чтобы определить, согласуется ли он с подписью в jwt.
Как определить, что срок действия токена истек?
применение
Из приведенного выше видно, что jwt не шифрует данные, а подписывает данные, чтобы гарантировать, что они не будут подделаны. Помимо использования при входе в систему, его также можно использовать для проверки электронной почты и графического кода подтверждения.
Капча
При входе в систему, если вы введете неправильный пароль слишком много раз, появится графический код подтверждения.
Принцип графического кода проверки заключается в том, чтобы предоставить клиенту графику и сохранить строку в паре с изображением на стороне сервера, что в прошлом в основном реализовывалось сеансом.
Строка в паре с проверочным кодом может использоваться в качестве секрета для проверки без сохранения состояния.
const jwt = require('jsonwebtoken')
// 假设验证码为字符验证码,字符为 ACDE,10分钟失效
const token = jwt.sign({ userId: 10085 }, secrect + 'ACDE', { expiresIn: 60 * 10 })
Подтверждение по элетронной почте
Теперь веб-сайт будет проверять почтовый ящик после успешной регистрации.Конкретный метод заключается в отправке ссылки на почтовый ящик, и пользователь щелкает ссылку, и проверка проходит успешно.
// 把邮箱以及用户id绑定在一起
const code = jwt.sign({ email, userId }, secret, { expiresIn: 60 * 30 })
// 在此链接校验验证码
const link = `https://example.com/code=${code}`
Без гражданства против с сохранением состояния
Что касается stateless и stateful, есть также сравнения в других технических направлениях, таких как компонент React без состояния и компонент с состоянием.Побочные эффекты в функциональном программировании можно понимать как состояние, а http также является протоколом без состояния, для которого требуются заголовки и файлы cookie для переноса. государство.
В аутентификации пользователей состояние означает, следует ли полагаться на внешнее хранилище данных, такое как mysql, redis и т. д.
Подумайте, как использовать сеанс и jwt для реализации следующих вопросов о входе в систему.
Как я могу аннулировать этот токен, когда пользователь выходит из системы
Поскольку jwt не имеет состояния и не сохраняет информацию об устройстве пользователя, он не может просто использовать ее для решения вышеуказанных проблем.Вы можете использовать базу данных для сохранения некоторых состояний для завершения.
- сеанс: просто очистите токен, соответствующий user_id
- jwt: используйте redis для ведения черного списка и добавляйте черный список (подпись) при выходе пользователя из системы.Время истечения срока действия соответствует времени истечения срока действия jwt.
Как разрешить пользователям входить в систему только на одном устройстве, например WeChat
- сеанс: использовать базу данных sql, добавить поле токена и индекс в таблицу пользовательской базы данных, сбросить поле токена каждый раз, когда вы входите в систему, и найти user_id в соответствии с токеном каждый раз, когда вы запрашиваете интерфейс разрешений.
- jwt: если вы используете базу данных типа sql, добавьте поле токена в таблицу пользовательской базы данных (не нужно добавлять индекс), сбрасывайте поле токена каждый раз, когда вы входите в систему, и каждый раз, когда вы запрашиваете интерфейс разрешений, получайте user_id в соответствии с jwt и проверьте таблицу пользователей в соответствии с user_id, чтобы получить токен. Определите, согласованы ли токены. В качестве альтернативы вы можете использовать метод счетчика, как в следующем вопросе.
Для этого требования сессия немного проще, ведь jwt тоже должен полагаться на базу данных.
Как разрешить пользователям входить в систему только на последних пяти устройствах, таких как многие игроки
- сеанс: используйте базу данных типа sql для создания таблицы базы данных токенов с тремя полями: идентификатор, токен и user_id.Таблицы пользователей и токенов имеют отношение 1: m. Добавьте строку для каждого входа. Получите user_id в соответствии с токеном, а затем получите количество устройств, на которых пользователь вошел в систему в соответствии с user_id.Если их больше 5, удалите строку с наименьшим идентификатором.
- jwt: используйте счетчик, используйте базу данных sql, добавьте счетчик полей в пользовательскую таблицу, значение по умолчанию равно 0, поле счетчика увеличивается на 1 каждый раз, когда вы входите в систему, а полезная нагрузка jwt, создаваемая при каждом входе в систему, содержит данные current_count — это значение счетчика пользователя. Каждый раз, когда запрашивается интерфейс разрешений, счетчик и текущий_счет получаются из jwt, а счетчик получается из пользовательской таблицы в соответствии с user_id, и если разница с текущим_счетом меньше 5
Для этого требования jwt немного проще, а использование сеанса требует ведения дополнительной таблицы токенов.
Как разрешить пользователям входить в систему только на последних пяти устройствах и заставить пользователя отключать все другие устройства, кроме существующего устройства, например, многих игроков
- сеанс: на основе предыдущего вопроса удалите все записи токенов, кроме устройства.
- jwt: На основе предыдущего вопроса добавьте количество + 5 и переназначьте устройство на новый счет.
Как отобразить список устройств, на которых зарегистрирован этот пользователь / Как выгнать определенного пользователя
- сеанс: добавить новое устройство столбца в таблицу токенов
- jwt: сервер должен хранить информацию о списке устройств, практика такая же, как и в сеансе, использование jwt не имеет смысла.
Суммировать
Из приведенных выше вопросов, если вам не нужно контролировать количество зарегистрированных устройств и информацию об устройстве, jwt без сохранения состояния является хорошим выбором. Как только информация об устройстве задействована, в jwt необходимо добавить дополнительную поддержку состояния, что усложняет аутентификацию.В этом случае сеанс является хорошим выбором.
jwt не является панацеей.Использовать или не использовать jwt нужно решать в соответствии с потребностями бизнеса.