JavaRush /Курси /Модуль 2: Fullstack /Безпека та управління доступом

Безпека та управління доступом

Модуль 2: Fullstack
Рівень 18 , Лекція 5
Відкрита

6.1 Аутентифікація та авторизація користувачів

На цьому етапі ми розглянемо, як забезпечити безпеку нашого багатоконтейнерного застосунку та управління доступом. Це включає аутентифікацію користувачів, шифрування даних, захист API та налаштування безпечних з'єднань між сервісами.

Ціль: забезпечити, щоб тільки зареєстровані та аутентифіковані користувачі могли взаємодіяти із застосунком та виконувати операції.

Реалізація JWT (JSON Web Token) для аутентифікації

Крок 1. Встановлення необхідних бібліотек:

Terminal

pip install Flask-JWT-Extended

Крок 2. Налаштування JWT у Flask-застосунку:

Додайте наступні зміни у файл backend/app/__init__.py:

Python

from flask_jwt_extended import JWTManager

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://taskuser:taskpassword@database:5432/taskdb'
app.config['JWT_SECRET_KEY'] = 'your_jwt_secret_key'  # Замініть на ваш секретний ключ
db = SQLAlchemy(app)
jwt = JWTManager(app)
        
from app import routes    

Крок 3. Створення маршрутів для реєстрації та авторизації:

Додайте наступні маршрути у файл backend/app/routes.py:

Python

from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
from werkzeug.security import generate_password_hash, check_password_hash
from app.models import User, Task
        
@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    hashed_password = generate_password_hash(data['password'], method='sha256')
    new_user = User(username=data['username'], password=hashed_password)
    db.session.add(new_user)
    db.session.commit()
    return jsonify({'message': 'User registered successfully'}), 201
        
@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    user = User.query.filter_by(username=data['username']).first()
    if not user or not check_password_hash(user.password, data['password']):
        return jsonify({'message': 'Invalid credentials'}), 401

    access_token = create_access_token(identity=user.id)
    return jsonify({'access_token': access_token}), 200

@app.route('/tasks', methods=['GET'])
@jwt_required()
def get_tasks():
    current_user_id = get_jwt_identity()
    tasks = Task.query.filter_by(owner_id=current_user_id).all()
    return jsonify([task.to_dict() for task in tasks])

Крок 4. Оновлення моделі User для зберігання паролів:

Оновіть файл backend/app/models.py:

Python

from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)
    tasks = db.relationship('Task', backref='owner', lazy=True)

6.2 Шифрування даних

Мета: забезпечити захист даних при передачі між клієнтом і сервером.

Використання HTTPS

Крок 1. Налаштування Nginx як реверс-проксі з підтримкою HTTPS:

Створіть файл nginx.conf в кореневій директорії проекту:

Текст

server {
    listen 80;
    server_name your_domain.com;
        
    location / {
        proxy_pass http://frontend:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
        
    location /api {
        proxy_pass http://backend:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Крок 2. Створення Dockerfile для Nginx:

Створіть файл Dockerfile у директорії nginx:

dockerfile

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf

Крок 3. Додавання Nginx у compose.yaml:

Оновіть файл compose.yaml, додавши сервіс для Nginx:

Yaml

version: '3'

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    networks:
      - task-network
        
  backend:
    build: ./backend
    ports:
      - "5000:5000"
    depends_on:
      - database
    networks:
      - task-network
    environment:
      - DATABASE_URL=postgresql://taskuser:taskpassword@database:5432/taskdb
        
  database:
    image: postgres:13
    environment:
      - POSTGRES_DB=taskdb
      - POSTGRES_USER=taskuser
      - POSTGRES_PASSWORD=taskpassword
    networks:
      - task-network
    volumes:
      - db-data:/var/lib/postgresql/data
        
  nginx:
    build: ./nginx
    ports:
      - "80:80"
    depends_on:
      - frontend
      - backend
    networks:
      - task-network
        
networks:
  task-network:
    driver: bridge
        
volumes:
  db-data:

6.3 Отримання SSL сертифіката за допомогою Let's Encrypt

Крок 1. Встановлення Certbot:

Дотримуйтесь інструкцій на офіційному сайті Certbot для встановлення Certbot.

Крок 2. Отримання сертифіката:

Terminal

sudo certbot certonly --standalone -d your_domain.com

Крок 3. Налаштування Nginx для використання SSL:

Оновіть nginx.conf для використання SSL:

Text

server {
    listen 80;
    server_name your_domain.com;
    return 301 https://$host$request_uri;
}
        
server {
    listen 443 ssl;
    server_name your_domain.com;
        
    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
        
    location / {
        proxy_pass http://frontend:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
        
    location /api {
        proxy_pass http://backend:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Крок 4. Оновлення Dockerfile для Nginx для копіювання сертифікатів:

dockerfile

FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY /etc/letsencrypt /etc/letsencrypt

6.4 Захист API

Мета: обмежити доступ до API та запобігти несанкціонованим запитам.

Використання JWT для захисту маршрутів

Ми вже додали захист для маршрутів задач, використовуючи декоратор @jwt_required(). Переконайтеся, що всі чутливі маршрути захищені цим декоратором:

Python

from flask_jwt_extended import jwt_required, get_jwt_identity

@app.route('/tasks', methods=['GET'])
@jwt_required()
def get_tasks():
    current_user_id = get_jwt_identity()
    tasks = Task.query.filter_by(owner_id=current_user_id).all()
    return jsonify([task.to_dict() for task in tasks])

Обмеження доступу до бази даних

Мета: запобігти несанкціонованому доступу до бази даних.

Налаштування ролей та привілеїв

Крок 1. Створення користувача із обмеженими привілеями:

SQL

CREATE USER limited_user WITH PASSWORD 'limited_password';
GRANT CONNECT ON DATABASE taskdb TO limited_user;
GRANT USAGE ON SCHEMA public TO limited_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO limited_user;

Крок 2. Оновлення змінної середовища DATABASE_URL:

Оновіть змінну середовища DATABASE_URL у файлі compose.yaml:

Yaml

environment:
  - DATABASE_URL=postgresql://limited_user:limited_password@database:5432/taskdb
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ