JSON Web Token (JWT) — это компактный, безопасный и автономный способ передачи информации между сторонами в виде JSON-объекта. JWT часто используется для аутентификации и авторизации в современных веб-приложениях и микросервисных архитектурах.
JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для безопасной передачи информации между сторонами в формате JSON. Он содержит утверждения (claims) о сущности (обычно пользователе) и дополнительных данных. JWT подписывается с использованием секретного ключа или пары ключей (например, с использованием алгоритмов HMAC или RSA), что обеспечивает целостность и подлинность данных.
JWT состоит из трех частей, разделенных точками (.
):
xxxxx.yyyyy.zzzzz
xxxxx
— закодированный Headeryyyyy
— закодированный Payloadzzzzz
— Signature{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "Иван Иванов",
"admin": true,
"iat": 1516239022
}
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret_key
)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6
IkpvaG4gSmltYW5vdiIsImFkbWluIjp0cnVl
LCJpYXQiOjE1MTYyMzkwMjJ9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Authorization
при последующих запросах к защищенным ресурсам.JWT часто используется для подтверждения личности пользователя. После успешной аутентификации пользователь получает токен, который используется для доступа к защищенным ресурсам без необходимости повторного ввода учетных данных.
Помимо аутентификации, JWT может содержать информацию о правах доступа пользователя (например, роли), что позволяет серверу управлять доступом к различным ресурсам.
JWT может использоваться для безопасной передачи информации между сервисами или микросервисами, обеспечивая целостность и подлинность данных.
HS256
или RS256
. Избегайте использования none
в качестве алгоритма.exp
) для токенов, чтобы минимизировать риск их использования после компрометации.pip install PyJWT
import jwt
import datetime
# Секретный ключ для подписания токена
SECRET_KEY = 'your-secret-key'
# Создание токена
def create_token(user_id, username):
payload = {
'user_id': user_id,
'username': username,
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1), # Токен действителен 1 час
'iat': datetime.datetime.utcnow(),
'nbf': datetime.datetime.utcnow()
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
return token
# Проверка токена
def verify_token(token):
try:
decoded = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
return decoded
except jwt.ExpiredSignatureError:
print("Токен истек")
except jwt.InvalidTokenError:
print("Неверный токен")
# Пример использования
if __name__ == "__main__":
token = create_token(123, 'akrom')
print(f"JWT токен: {token}")
decoded_payload = verify_token(token)
if decoded_payload:
print(f"Декодированные данные: {decoded_payload}")
npm install jsonwebtoken
const jwt = require('jsonwebtoken');
// Секретный ключ для подписания токена
const SECRET_KEY = 'your-secret-key';
// Создание токена
function createToken(userId, username) {
const payload = {
user_id: userId,
username: username
};
const options = {
expiresIn: '1h'
};
const token = jwt.sign(payload, SECRET_KEY, options);
return token;
}
// Проверка токена
function verifyToken(token) {
try {
const decoded = jwt.verify(token, SECRET_KEY);
return decoded;
} catch (err) {
if (err.name === 'TokenExpiredError') {
console.log('Токен истек');
} else {
console.log('Неверный токен');
}
}
}
// Пример использования
const token = createToken(123, 'akrom');
console.log(`JWT токен: ${token}`);
const decoded = verifyToken(token);
if (decoded) {
console.log('Декодированные данные:', decoded);
}
Добавьте зависимость в ваш pom.xml
для Maven:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- или jjwt-gson, если вы предпочитаете Gson -->
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import java.util.Date;
public class JwtExample {
// Секретный ключ для подписания токена
private static final String SECRET_KEY = "your-secret-key";
// Создание токена
public static String createToken(long userId, String username) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
Date exp = new Date(nowMillis + 3600000); // 1 час
return Jwts.builder()
.setSubject(Long.toString(userId))
.claim("username", username)
.setIssuedAt(now)
.setExpiration(exp)
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Проверка токена
public static Claims verifyToken(String token) {
try {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
return claims;
} catch (ExpiredJwtException e) {
System.out.println("Токен истек");
} catch (SignatureException e) {
System.out.println("Неверная подпись токена");
} catch (Exception e) {
System.out.println("Неверный токен");
}
return null;
}
// Пример использования
public static void main(String[] args) {
String token = createToken(123, "akrom");
System.out.println("JWT токен: " + token);
Claims claims = verifyToken(token);
if (claims != null) {
System.out.println("Декодированные данные:");
System.out.println("user_id: " + claims.getSubject());
System.out.println("username: " + claims.get("username"));
System.out.println("exp: " + claims.getExpiration());
}
}
}
JWT можно хранить на клиентской стороне различными способами. Выбор метода хранения влияет на безопасность приложения.
JWT обычно имеют ограниченный срок действия для минимизации рисков компрометации. Для обеспечения непрерывного доступа можно использовать механизм обновления токенов:
JWT, будучи самодостаточными, сложно отзывать без дополнительной инфраструктуры. Возможные подходы:
HS256
, RS256
и другие проверенные алгоритмы.exp
) для ограничения времени использования токена.exp
, iss
, aud
) проверяются на сервере.JSON Web Token (JWT) представляет собой мощный инструмент для аутентификации и авторизации в современных приложениях. Его компактность, самодостаточность и стандартизированность делают его популярным выбором для разработки безопасных и масштабируемых систем. Однако при использовании JWT важно учитывать аспекты безопасности, управлять сроками действия токенов и применять лучшие практики для минимизации рисков. Правильная реализация и управление JWT помогут обеспечить надежную защиту данных и эффективную работу приложения.
1. Чем отличается JWT от сессий?
JWT является самодостаточным токеном, который хранит информацию о пользователе и его правах доступа. В отличие от традиционных сессий, где состояние хранится на сервере, JWT не требует хранения сессий на сервере, что облегчает масштабирование. Однако управление отзывом токенов может быть сложнее.
2. Можно ли шифровать JWT?
Да, JWT можно не только подписывать, но и шифровать, используя спецификацию JWE (JSON Web Encryption). Это позволяет скрыть содержимое токена от посторонних глаз. Однако в большинстве случаев достаточно подписанного JWT (JWS).
3. Как защититься от атак CSRF при использовании JWT в куки?
Используйте двойную отправку куки (Double Submit Cookie) или включите CSRF-токены, которые проверяются на сервере при каждом запросе. Также рассмотрите использование SameSite атрибута для куки.
4. Можно ли использовать JWT для аутентификации в мобильных приложениях?
Да, JWT широко используется для аутентификации в мобильных приложениях. Важно обеспечить безопасное хранение токенов на устройстве и передавать их по защищенному каналу.
5. Что делать, если секретный ключ был скомпрометирован?
Немедленно обновите секретный ключ и отзовите все текущие токены. Это может потребовать реализации механизма отзыва токенов или использования коротких сроков действия токенов.