CodeGym /Các khóa học /Docker SELF /Bảo mật và quản lý quyền truy cập

Bảo mật và quản lý quyền truy cập

Docker SELF
Mức độ , Bài học
Có sẵn

6.1 Xác thực và phân quyền người dùng

Ở giai đoạn này, chúng ta sẽ tìm hiểu cách bảo mật ứng dụng đa container và quản lý quyền truy cập. Điều này bao gồm xác thực người dùng, mã hóa dữ liệu, bảo vệ API và thiết lập kết nối an toàn giữa các dịch vụ.

Mục tiêu: đảm bảo rằng chỉ những người dùng đã đăng ký và được xác thực mới có thể tương tác với ứng dụng và thực hiện các thao tác.

Triển khai JWT (JSON Web Token) cho xác thực

Bước 1. Cài đặt các thư viện cần thiết:

Terminal

pip install Flask-JWT-Extended

Bước 2. Cấu hình JWT trong ứng dụng Flask:

Thêm các thay đổi sau vào file 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'  # Thay bằng khóa bí mật của bạn
db = SQLAlchemy(app)
jwt = JWTManager(app)
        
from app import routes    

Bước 3. Tạo các route cho đăng ký và đăng nhập:

Thêm các route sau vào file 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': 'Người dùng đã đăng ký thành công'}), 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': 'Thông tin đăng nhập không hợp lệ'}), 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])

Bước 4. Cập nhật model User để lưu trữ mật khẩu:

Cập nhật file 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 Mã hóa dữ liệu

Mục tiêu: đảm bảo bảo vệ dữ liệu khi truyền giữa client và server.

Sử dụng HTTPS

Bước 1. Cấu hình Nginx làm reverse proxy hỗ trợ HTTPS:

Tạo file nginx.conf trong thư mục gốc của dự án:

Text

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;
    }
}

Bước 2. Tạo Dockerfile cho Nginx:

Tạo file Dockerfile trong thư mục nginx:

dockerfile

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

Bước 3. Thêm Nginx vào compose.yaml:

Cập nhật file compose.yaml, thêm service cho 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 Nhận SSL Certificate bằng Let's Encrypt

Bước 1. Cài đặt Certbot:

Làm theo hướng dẫn trên trang web chính thức của Certbot để cài đặt Certbot.

Bước 2. Nhận chứng chỉ:

Terminal

sudo certbot certonly --standalone -d your_domain.com

Bước 3. Cấu hình Nginx để sử dụng SSL:

Cập nhật nginx.conf để sử dụng 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;
    }
}

Bước 4. Cập nhật Dockerfile cho Nginx để copy chứng chỉ:

dockerfile

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

6.4 Bảo vệ API

Mục tiêu: giới hạn quyền truy cập vào API và ngăn chặn các yêu cầu không được phép.

Sử dụng JWT để bảo vệ các route

Chúng ta đã thêm bảo vệ cho các route của task bằng cách sử dụng decorator @jwt_required(). Đảm bảo rằng tất cả các route nhạy cảm đều được bảo vệ bởi decorator này:

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])

Hạn chế quyền truy cập vào cơ sở dữ liệu

Mục tiêu: ngăn chặn truy cập trái phép vào cơ sở dữ liệu.

Cấu hình vai trò và quyền

Bước 1. Tạo user với quyền hạn chế:

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;

Bước 2. Cập nhật biến môi trường DATABASE_URL:

Cập nhật biến môi trường DATABASE_URL trong file compose.yaml:

Yaml

environment:
  - DATABASE_URL=postgresql://limited_user:limited_password@database:5432/taskdb
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION