1
0
Fork 0
mirror of https://github.com/EDeev/deev.space.git synced 2026-10-08 04:59:31 +03:00
deev.space/main/middleware.py
Egor Deev 878b4580e4 Версия 2.0: код с продакшена deev.space
Перенесено всё, что накопилось на сервере с декабря 2025:
- анонимный посетитель по подписанной cookie (main/middleware.py), лайки и дизлайки
  без регистрации с антинакруткой, уникальные просмотры статей;
- карточка-паспорт, стек в одну строку, блок «В цифрах»;
- миграции 0005–0008, команды load_initial_data и populate_demo, robots.txt;
- обновлённые шаблоны, стили и скрипты.

Безопасность и порядок:
- все секреты только из окружения, значения по умолчанию пустые;
- DEBUG по умолчанию выключен, без DJANGO_SECRET_KEY запуск в бою невозможен;
- ALLOWED_HOSTS, путь к базе и SSL-редирект настраиваются переменными;
- убрана статика админки Django (результат collectstatic) и media из git;
- добавлены .gitignore и .gitattributes (переводы строк — LF).
2026-10-02 11:58:54 +00:00

50 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Анонимный идентификатор посетителя (для оценок и уникальных просмотров без регистрации)."""
import hashlib
import ipaddress
import uuid
from django.conf import settings
COOKIE = 'dspace_vid'
SALT = 'dspace-visitor'
MAX_AGE = 365 * 24 * 3600
class VisitorMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
vid = request.get_signed_cookie(COOKIE, default=None, salt=SALT)
fresh = not vid
if fresh:
vid = uuid.uuid4().hex
request.visitor_id = vid
response = self.get_response(request)
if fresh:
response.set_signed_cookie(
COOKIE, vid, salt=SALT, max_age=MAX_AGE, httponly=True,
secure=not settings.DEBUG, samesite='Lax'
)
return response
def client_ip_hash(request):
"""Хэш IP + User-Agent с солью; пустая строка, если реальный IP не виден (loopback/частная сеть)."""
ip = (request.META.get('HTTP_X_REAL_IP') or request.META.get('REMOTE_ADDR') or '').strip()
try:
addr = ipaddress.ip_address(ip)
except ValueError:
return ''
if addr.is_loopback or addr.is_private:
return ''
ua = request.META.get('HTTP_USER_AGENT', '')
return hashlib.sha256(f'{settings.SECRET_KEY}|{ip}|{ua}'.encode()).hexdigest()
BOT_MARKERS = ('bot', 'spider', 'crawl', 'slurp', 'preview', 'curl', 'wget', 'python-requests', 'headless')
def is_bot(request):
ua = request.META.get('HTTP_USER_AGENT', '').lower()
return not ua or any(m in ua for m in BOT_MARKERS)