6.1 İstifadəçilərin autentifikasiyası və avtorizasiyası
Bu mərhələdə bizim çox konteynerli tətbiqimizi necə təhlükəsiz etmək və giriş idarəsini təmin etmək barədə danışacağıq. Bura istifadəçilərin autentifikasiyası, məlumat şifrələnməsi, API qorunması və servislər arasında təhlükəsiz əlaqələrin qurulması daxildir.
Məqsəd: Yalnız qeydiyyatdan keçmiş və autentifikasiya olunmuş istifadəçilərin tətbiq ilə əlaqə qura bilməsi və əməliyyatlar həyata keçirməsini təmin etməkdir.
JWT (JSON Web Token) vasitəsilə autentifikasiya implementasiyası
1-ci addım. Lazım olan kitabxanaların quraşdırılması:
pip install Flask-JWT-Extended
2-ci addım. Flask-tətbiqdə JWT-in tənzimlənməsi:
Aşağıdakı dəyişiklikləri backend/app/__init__.py
faylına əlavə edin:
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' # Sizin gizli açarınızla dəyişdirin
db = SQLAlchemy(app)
jwt = JWTManager(app)
from app import routes
3-cü addım. Qeydiyyat və avtorizasiya üçün route-ların yaradılması:
Aşağıdakı route-ları backend/app/routes.py
faylına əlavə edin:
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
@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': 'İstifadəçi uğurla qeydiyyatdan keçdi'}), 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': 'Yanlış məlumat'}), 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-cü addım. Şifrələrin saxlanması üçün User modelinin yenilənməsi:
backend/app/models.py
faylını yeniləyin:
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əlumatların Şifrələnməsi
Məqsəd: Müştəri və server arasında məlumatların ötürülməsi zamanı onların mühafizəsini təmin etmək.
HTTPS-in istifadəsi
Addım 1. HTTPS dəstəyi ilə Nginx-i reverse-proxy kimi qurmaq:
Layihənin kök direktivində nginx.conf faylı yaradın:
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;
}
}
Addım 2. Nginx üçün Dockerfile yaratmaq:
nginx direktivində Dockerfile faylı yaradın:
FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
Addım 3. Nginx-i docker-compose.yml
-ə əlavə etmək:
docker-compose.yml
faylını yeniləyin və Nginx üçün yeni bir servis əlavə edin:
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 Let's Encrypt vasitəsilə SSL sertifikatı əldə etmək
Adım 1. Certbot-un quraşdırılması:
Quraşdırma üçün Certbot-un rəsmi saytındakı təlimatlara əməl edin.
Adım 2. Sertifikatı əldə etmək:
sudo certbot certonly --standalone -d your_domain.com
Adım 3. SSL istifadə etmək üçün Nginx-in sazlanması:
SSL istifadə etmək üçün nginx.conf faylını yeniləyin:
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;
}
}
Adım 4. Sertifikatları kopyalamaq üçün Nginx üçün Dockerfile-ın yenilənməsi:
FROM nginx:latest
COPY nginx.conf /etc/nginx/nginx.conf
COPY /etc/letsencrypt /etc/letsencrypt
6.4 API müdafiəsi
Məqsəd: API-yə girişləri məhdudlaşdırmaq və icazəsiz sorğuların qarşısını almaq.
Marşrutların müdafiəsi üçün JWT istifadəsi
Artıq marşrut tapşırıqlarını qorumaq üçün @jwt_required()
dekoratorundan istifadə etdik. Bütün həssas marşrutların bu dekoratorla qorunduğundan əmin olun:
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])
Verilənlər bazasına girişin məhdudlaşdırılması
Məqsəd: Verilənlər bazasına icazəsiz girişin qarşısını almaq.
Rolların və imtiyazların sazlanması
Addım 1. Məhdudlaşdırılmış imtiyazlara malik istifadəçi yaradın:
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;
Addım 2. DATABASE_URL
mühit dəyişənini yeniləyin:
docker-compose.yml
faylındakı DATABASE_URL
mühit dəyişənini yeniləyin:
environment:
- DATABASE_URL=postgresql://limited_user:limited_password@database:5432/taskdb
GO TO FULL VERSION