Новая Школа - онлайн-школа подготовки к ЕГЭ
Задача Задача №3383080
А
Аноним
12 сентября 2025 13:30 · публичный вопрос
А
Аноним

Код авторизации для сайта и приложения

Ответ нейросети
12 сентября 2025 13:30

Ниже подробное решение по теме авторизации для сайта и мобильного приложения. Я предложу простой, понятный и безопасный подход с использованием JSON Web Token (JWT). Это подходит для школьной задачи по информатике и легко адаптируется под сайт и под мобильное приложение.

Что будет сделано

  • Объяснение потока авторизации (как и зачем).
  • Данные модели/структура (пользователь, пароль, токен).
  • Пример реализации на Python (Flask) и на JavaScript (Node.js с Express) — пошагово с кодом.
  • Ключевые замечания по безопасности и тестированию.
  • Коротко — как это использовать в мобильном приложении.
  1. Что такое поток авторизации с JWT и зачем он нужен
  • Пользователь вводит логин и пароль.
  • Сервер проверяет данные и возвращает токен JWT, который подтверждает личность пользователя.
  • Клиент (браузер или мобильное приложение) хранит токен и отправляет его в заголовке запроса Authorization: Bearer при обращении к защищённым ресурсам.
  • В ресурсах сервер проверяет подпись и срок действия токена, разрешая доступ, если токен валиден.

Плюсы JWT:

  • Простота внедрения и использование как на сайте, так и в мобильном приложении.
  • Нет необходимости держать сессию на сервере (stateless).

Минусы:

  • Токен должен храниться безопасно на клиенте (по возможности использовать httpOnly cookies или безопасное локальное хранилище в мобильном приложении).
  • Не забывайте про HTTPS и настройку срока действия токена.
  1. Модель данных (для учебной задачи)
  • Пользователь: id, username, password_hash
  • Токен: JWT, подписанный секретным ключом сервера, содержит данные sub (id пользователя) и exp (срок действия)
  1. Реализация на Python (Flask) — простой пример

prerequisites:

  • Python 3.x
  • Установить зависимости: pip install Flask PyJWT bcrypt

Код (Flask, файл app.py): """ from flask import Flask, request, jsonify import bcrypt import jwt from datetime import datetime, timedelta

app = Flask(name) SECRET_KEY = 'your-secret-key' # в продакшене хранить в env-переменной

Простое хранилище пользователей (в реальности — база данных)

users = {} # username -> {id, password_hash}

def hash_password(pw: str) -> bytes: return bcrypt.hashpw(pw.encode('utf-8'), bcrypt.gensalt())

def verify_password(pw: str, pw_hash: bytes) -> bool: return bcrypt.checkpw(pw.encode('utf-8'), pw_hash)

def create_token(user_id: int, username: str) -> str: payload = { 'sub': user_id, 'username': username, 'exp': datetime.utcnow() + timedelta(hours=1) # токен действителен 1 час } return jwt.encode(payload, SECRET_KEY, algorithm='HS256')

def decode_token(token: str): try: return jwt.decode(token, SECRET_KEY, algorithms=['HS256']) except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None

@app.route('/register', methods=['POST']) def register(): data = request.json if not data or 'username' not in data or 'password' not in data: return jsonify({'error': 'Missing username or password'}), 400 username = data['username'] password = data['password'] if username in users: return jsonify({'error': 'User already exists'}), 400

user_id = len(users) + 1
password_hash = hash_password(password)
users[username] = {'id': user_id, 'password_hash': password_hash}
return jsonify({'message': 'User registered', 'user_id': user_id}), 201

@app.route('/login', methods=['POST']) def login(): data = request.json if not data or 'username' not in data or 'password' not in data: return jsonify({'error': 'Missing username or password'}), 400

username = data['username']
password = data['password']

user_record = users.get(username)
if not user_record:
    return jsonify({'error': 'Invalid credentials'}), 401

if not verify_password(password, user_record['password_hash']):
    return jsonify({'error': 'Invalid credentials'}), 401

token = create_token(user_record['id'], username)
return jsonify({'token': token})

@app.route('/protected', methods=['GET']) def protected(): auth_header = request.headers.get('Authorization', '') if not auth_header.startswith('Bearer '): return jsonify({'error': 'Missing or invalid Authorization header'}), 401 token = auth_header.split(' ')[1] payload = decode_token(token) if not payload: return jsonify({'error': 'Invalid or expired token'}), 401

return jsonify({'message': f'Welcome {payload["username"]}! This is protected data.'})

if name == 'main': app.run(debug=True) """

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

  • Регистрация: отправить POST /register с JSON {"username": "user1", "password": "pass"}.
  • Вход: POST /login с тем же JSON. В ответе будет token.
  • Доступ к защищённому: GET /protected с заголовком Authorization: Bearer .
  1. Реализация на JavaScript (Node.js + Express) — пример

prerequisites:

  • Node.js
  • Установить зависимости: npm init -y npm install express body-parser bcryptjs jsonwebtoken

Код (Express, файл server.js): """ const express = require('express'); const bodyParser = require('body-parser'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken');

const app = express(); app.use(bodyParser.json());

const SECRET = 'your-secret-key'; // храните в env

// Простое хранилище пользователей const users = {}; // username -> { id, passwordHash }

function createToken(userId, username) { const payload = { sub: userId, username: username, exp: Math.floor(Date.now() / 1000) + 60 * 60 }; return jwt.sign(payload, SECRET); }

function verifyToken(token) { try { return jwt.verify(token, SECRET); } catch (e) { return null; } }

app.post('/register', (req, res) => { const { username, password } = req.body; if (!username || !password) return res.status(400).json({ error: 'Missing username or password' }); if (users[username]) return res.status(400).json({ error: 'User already exists' });

const id = Object.keys(users).length + 1; const hash = bcrypt.hashSync(password, 10); users[username] = { id, passwordHash: hash }; res.status(201).json({ message: 'User registered', userId: id }); });

app.post('/login', (req, res) => { const { username, password } = req.body; if (!username || !password) return res.status(400).json({ error: 'Missing username or password' });

const user = users[username]; if (!user) return res.status(401).json({ error: 'Invalid credentials' });

const valid = bcrypt.compareSync(password, user.passwordHash); if (!valid) return res.status(401).json({ error: 'Invalid credentials' });

const token = createToken(user.id, username); res.json({ token }); });

app.get('/protected', (req, res) => { const authHeader = req.headers['authorization']; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: 'Missing or invalid Authorization header' }); } const token = authHeader.split(' ')[1]; const payload = verifyToken(token); if (!payload) return res.status(401).json({ error: 'Invalid or expired token' });

res.json({ message: Welcome ${payload.username}! This is protected data. }); });

app.listen(3000, () => console.log('Server running on localhost')); """

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

  • Регистрация: POST localhost с JSON {"username": "user1", "password": "pass"}.
  • Вход: POST localhost с тем же JSON. В ответе будет token.
  • Доступ к защищённому: GET localhost с заголовком Authorization: Bearer .
  1. Как использовать на мобильном приложении (кратко)
  • Приложение после успешной авторизации сохраняет полученный JWT в безопасном месте (secure storage).
  • При обращении к API отправляет заголовок Authorization: Bearer .
  • При истечении срока токена можно реализовать refresh-token механизм (разделить: access токен короткий срок + refresh-токен, который хранится в httpOnly cookie или в защищённом месте и обновляет access-токен).
  1. Замечания по безопасности
  • Не храните секретный ключ в коде. Используйте переменные окружения (ENV) и сервисы типа Vault.
  • Всегда используйте HTTPS для защиты токенов в пути и в покидании клиента.
  • Устанавливайте разумный срок жизни токена (например, 15–60 минут) и реализуйте механизм обновления токена (refresh token), чтобы не требовать повторную авторизацию часто.
  • Подумайте о дополнительных мерах: rate limiting, IP-ограничения, защиту от CSRF, проверку пароля на сложность, мониторинг аномалий.
  • Для SPA лучше рассматривать хранение токена в httpOnly cookies с защитой от CSRF или в безопасном хранилище на мобилки с дополнительными мерами.
  1. Краткие тестовые команды (пример)
  • Регистрация:
    • curl -X POST localhost -H "Content-Type: application/json" -d '{"username":"alice","password":"secret"}'
  • Логин:
    • curl -X POST localhost -H "Content-Type: application/json" -d '{"username":"alice","password":"secret"}'
  • Доступ к защищённому:
    • curl -H "Authorization: Bearer <полученный токен>" localhost

Если хочешь, могу адаптировать решение под конкретный стек (например, Django, FastAPI, Laravel, ASP.NET) или показать более подробный пример с OAuth 2.0 Authorization Code Flow для сайта и мобильного приложения. Также могу добавить простой клиент для мобильной платформы (React Native или Flutter) в виде псевдокода или полноценных примеров. Что предпочитаете?