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

Как получить токен на сервере?

1.0 Junior🔥 241 комментариев
#REST API и HTTP#Безопасность

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

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

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

Как получить токен на сервере

Получение токена — это критический процесс аутентификации. Покажу основные методы.

Метод 1: Basic Authentication

Используешь логин и пароль в заголовке Authorization. Базовый метод, но небезопасен без HTTPS.

import base64
from flask import request, jsonify

@app.route('/api/token', methods=['POST'])
def get_token():
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Basic '):
        return jsonify({'error': 'No Basic auth'}), 401
    
    encoded = auth_header[6:]
    decoded = base64.b64decode(encoded).decode('utf-8')
    username, password = decoded.split(':', 1)
    
    user = db.query(User).filter_by(username=username).first()
    if not user or not verify_password(password, user.hashed_password):
        return jsonify({'error': 'Invalid credentials'}), 401
    
    token = create_jwt_token(user.id)
    return jsonify({'access_token': token, 'token_type': 'Bearer'})

Метод 2: JSON с логином и паролем

Более удобен для фронтенда — передаёшь данные в JSON теле запроса.

@app.route('/api/login', methods=['POST'])
def login():
    data = request.json
    username = data.get('username')
    password = data.get('password')
    
    user = db.query(User).filter_by(username=username).first()
    if not user or not verify_password(password, user.hashed_password):
        return jsonify({'error': 'Invalid credentials'}), 401
    
    access_token = create_jwt_token(user.id, expires_in=900)
    refresh_token = create_jwt_token(user.id, expires_in=2592000)
    
    return jsonify({
        'access_token': access_token,
        'refresh_token': refresh_token,
        'token_type': 'Bearer',
        'expires_in': 900,
    })

Метод 3: OAuth 2.0

Для интеграций и третьих приложений.

import secrets
from datetime import datetime, timedelta

@app.route('/oauth/token', methods=['POST'])
def oauth_token():
    grant_type = request.form.get('grant_type')
    
    if grant_type == 'password':
        username = request.form.get('username')
        password = request.form.get('password')
        
        user = db.query(User).filter_by(username=username).first()
        if not user or not verify_password(password, user.hashed_password):
            return jsonify({'error': 'invalid_credentials'}), 401
        
        access_token = secrets.token_urlsafe(64)
        return jsonify({
            'access_token': access_token,
            'token_type': 'Bearer',
            'expires_in': 3600,
        })

Метод 4: Service Account (сервер-к-серверу)

Для микросервисов и фоновых задач.

import jwt
from datetime import datetime, timedelta

class ServiceAccountManager:
    def __init__(self, private_key: str, service_account_id: str):
        self.private_key = private_key
        self.service_account_id = service_account_id
    
    def create_access_token(self, expires_in: int = 3600) -> str:
        now = datetime.utcnow()
        payload = {
            'iss': self.service_account_id,
            'aud': 'https://api.example.com',
            'exp': now + timedelta(seconds=expires_in),
            'iat': now,
        }
        return jwt.encode(payload, self.private_key, algorithm='RS256')

Метод 5: API Key

Для долгоживущих ключей, которые не истекают.

import secrets

@app.route('/api/generate-key', methods=['POST'])
def generate_api_key():
    api_key = f"sk_{secrets.token_urlsafe(32)}"
    
    db.add(APIKey(
        key=hash_api_key(api_key),
        user_id=current_user.id
    ))
    db.commit()
    
    return jsonify({
        'api_key': api_key,
        'message': 'Store this securely'
    })

Общая функция создания JWT

from datetime import datetime, timedelta
import jwt

SECRET_KEY = 'your-secret-key'
ALGORITHM = 'HS256'

def create_jwt_token(user_id: int, expires_in: int = 3600) -> str:
    now = datetime.utcnow()
    payload = {
        'user_id': user_id,
        'exp': now + timedelta(seconds=expires_in),
        'iat': now,
        'type': 'access',
    }
    return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)

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

Обязательно делай:

  • Используй HTTPS для всех запросов с токенами
  • Хэшируй пароли с bcrypt или argon2
  • Ограничивай попытки логина (rate limiting)
  • Делай короткоживущие access токены (15 минут)
  • Логируй все попытки получения токена
  • Используй refresh токены для обновления

Никогда не делай:

  • Не передавай пароли в GET параметрах
  • Не сохраняй токены в cookies без httpOnly флага
  • Не логируй полные токены
  • Не встраивай секреты в код

Рекомендуемый подход

  1. Пользователь отправляет POST /api/login с username и password
  2. Сервер проверяет credentials
  3. Если верно — выдаёт два токена:
    • Access token (15 мин, используется для API)
    • Refresh token (30 дней, используется для получения нового access)
  4. Клиент хранит tokens в памяти или secure storage
  5. При запросе к API отправляет access token в Authorization заголовке
  6. Когда access token истёк — клиент использует refresh token для получения нового