← Назад к вопросам

Что такое Access Token?

1.0 Junior🔥 151 комментариев
#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Access Token: безопасность и аутентификация

Access Token — это цифровой токен (обычно JWT), который выдаётся клиенту после успешной аутентификации. Он используется для доступа к защищённым ресурсам API без повторной отправки пароля на каждый запрос.

Как работает Access Token

Процесс аутентификации и авторизации:

1. Клиент отправляет username/password
      |
      v
2. Сервер проверяет учётные данные
      |
      v
3. Сервер генерирует Access Token (+ Refresh Token)
      |
      v
4. Клиент отправляет Token в заголовке каждого запроса
      |
      v
5. Сервер проверяет валидность Token
      |
      v
6. Если Token валиден → доступ к ресурсу
   Если Token истёк → используется Refresh Token

JWT (JSON Web Token) — самый популярный формат

// Access Token обычно это JWT, состоящий из 3 частей
// Header.Payload.Signature

// Пример JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

// Декодированный payload:
// {
//   "sub": "1234567890",      // Subject (user ID)
//   "name": "John Doe",       // User name
//   "iat": 1516239022,        // Issued at (время создания)
//   "exp": 1516242622         // Expiration (время истечения)
// }

Пример использования в Java с Spring Security

// 1. Генерация Access Token при логине
@Service
public class JwtTokenProvider {
    private static final String SECRET = "your-secret-key";
    private static final long EXPIRATION = 3600000; // 1 час
    
    public String generateAccessToken(String username, List<String> roles) {
        return Jwts.builder()
            .setSubject(username)
            .claim("roles", roles)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();
    }
    
    public String validateAndGetUsername(String token) {
        try {
            Claims claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
            return claims.getSubject();
        } catch (JwtException | IllegalArgumentException e) {
            throw new IllegalArgumentException("Invalid token", e);
        }
    }
}

// 2. Login endpoint
@RestController
@RequestMapping("/auth")
public class AuthController {
    @Autowired
    private JwtTokenProvider tokenProvider;
    
    @Autowired
    private AuthenticationManager authManager;
    
    @PostMapping("/login")
    public ResponseEntity<AuthResponse> login(@RequestBody LoginRequest request) {
        // Проверяем username и password
        Authentication auth = authManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                request.getUsername(),
                request.getPassword()
            )
        );
        
        UserDetails user = (UserDetails) auth.getPrincipal();
        String accessToken = tokenProvider.generateAccessToken(
            user.getUsername(),
            user.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .toList()
        );
        
        return ResponseEntity.ok(new AuthResponse(accessToken));
    }
}

// 3. Использование Token в защищённом endpoint
@RestController
@RequestMapping("/api")
public class UserController {
    @GetMapping("/profile")
    @PreAuthorize("isAuthenticated()")
    public ResponseEntity<UserProfile> getProfile(
        @AuthenticationPrincipal UserDetails user
    ) {
        // Token уже проверен Spring Security
        return ResponseEntity.ok(userService.getProfile(user.getUsername()));
    }
}

// 4. Клиент отправляет Token в каждом запросе
// Заголовок: Authorization: Bearer <access_token>
// GET /api/profile
// Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Жизненный цикл Token'а

// Access Token имеет ограниченное время жизни (обычно 15-60 минут)
// После истечения нужен Refresh Token для получения нового Access Token

@PostMapping("/refresh")
public ResponseEntity<AuthResponse> refreshToken(
    @RequestBody RefreshTokenRequest request
) {
    // Проверяем Refresh Token (обычно живёт дольше, 7-30 дней)
    String username = tokenProvider.validateRefreshToken(request.getRefreshToken());
    
    // Генерируем новый Access Token
    String newAccessToken = tokenProvider.generateAccessToken(username, roles);
    
    return ResponseEntity.ok(new AuthResponse(newAccessToken));
}

Безопасность Access Token

Чего НЕЛЬЗЯ делать:

// ❌ Хранить пароль в Token
Jwts.builder()
    .claim("password", user.getPassword())  // ОПАСНО!
    .build();

// ❌ Передавать Token в URL
GET /api/resource?token=eyJhbGc...  // ОПАСНО, логируется в логах

// ❌ Хранить sensitive данные в Token
Jwts.builder()
    .claim("creditCard", "4111-1111-1111-1111")  // ОПАСНО!
    .build();

// ❌ Использовать слабый SECRET
private static final String SECRET = "secret";  // Слишком короткий

Правильно:

// ✅ Хранить только user ID и минимум info
Jwts.builder()
    .setSubject(user.getId())  // Только ID
    .claim("roles", roles)      // Роли
    .build();

// ✅ Передавать Token в заголовке Authorization
// Authorization: Bearer <token>

// ✅ Использовать HTTPS для всех запросов

// ✅ Использовать strong SECRET (минимум 256 бит)
private static final String SECRET = "your-very-long-secret-key-with-minimum-256-bits-of-entropy";

// ✅ Хранить Access Token в памяти (не в localStorage в браузере)
// ✅ Хранить Refresh Token в secure HttpOnly Cookie

Access Token vs Refresh Token

Тип Token | Время жизни | Где хранить | Назначение
-----------+-------------+-------------+----------------------
Access    | 15-60 мин   | Память      | Доступ к ресурсам
Refresh   | 7-30 дней   | HttpOnly    | Получение новых
          |             | Cookie      | Access Token'ов

Сравнение с Session-based аутентификацией

// Token-based (Stateless)
// ✅ Масштабируемо (не требует session storage)
// ✅ Подходит для микросервисов
// ✅ Работает для мобильных приложений
// ❌ Сложнее реализовать logout (token продолжит работать)

// Session-based (Stateful)
// ✅ Легко сделать logout (удалить session)
// ✅ Проще контролировать активные сессии
// ❌ Требует sync между серверами
// ❌ Масштабируется хуже

Практический совет

Для продакшена рекомендую:

  1. Использовать JWT (Access Token) с коротким TTL (15 минут)
  2. Хранить Refresh Token в secure HttpOnly Cookie
  3. Всегда использовать HTTPS
  4. Генерировать strong SECRET ключи
  5. Добавить blacklist для logout (Redis)
  6. Мониторить попытки подделки Token'ов

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

Что такое Access Token? | PrepBro