Segurança do Sistema
Visão Geral de Segurança
O Acesso ao Emprego implementa medidas de segurança em múltiplas camadas, seguindo as melhores práticas para proteção de dados e privacidade dos usuários.
Arquitetura de Segurança Implementada
Princípios de Segurança Adotados
- Defesa em Profundidade: Múltiplas camadas de proteção
- Princípio do Menor Privilégio: Acesso mínimo necessário
- Separação de Responsabilidades: Isolamento de componentes
- Falha Segura: Sistema falha de forma controlada
- Conformidade LGPD: Proteção de dados pessoais
Camadas de Segurança
Aplicação:
- Autenticação JWT
- Validação de entrada
- Proteção CSRF
- Rate limiting básico
Dados:
- Criptografia de senhas
- Validação de CPF/email
- Sanitização de inputs
- Backup regular
Infraestrutura:
- HTTPS obrigatório
- Containers isolados
- Secrets management
- Logs de auditoria
Autenticação e Autorização
Sistema de Autenticação JWT
Implementação Atual:
# authentication.py
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate
class AuthenticationService:
"""Serviço de autenticação com JWT"""
@staticmethod
def login(email, password):
"""Autenticação de usuário"""
user = authenticate(email=email, password=password)
if user and user.is_active:
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
'user': {
'id': user.id,
'email': user.email,
'is_candidate': user.is_candidate,
'is_company': user.is_company,
'is_government_agent': user.is_government_agent
}
}
return None
@staticmethod
def refresh_token(refresh_token):
"""Renovação de token de acesso"""
try:
refresh = RefreshToken(refresh_token)
return {
'access': str(refresh.access_token)
}
except Exception:
return None
Configuração de Tokens:
# settings.py
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
}
Sistema de Permissões
Permissões Baseadas em Roles:
# permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""Permite edição apenas para o proprietário"""
def has_object_permission(self, request, view, obj):
# Leitura permitida para todos
if request.method in permissions.SAFE_METHODS:
return True
# Escrita apenas para o proprietário
return obj.user == request.user
class IsCandidateUser(permissions.BasePermission):
"""Permite acesso apenas para candidatos"""
def has_permission(self, request, view):
return request.user and request.user.is_candidate
class IsCompanyUser(permissions.BasePermission):
"""Permite acesso apenas para empresas"""
def has_permission(self, request, view):
return request.user and request.user.is_company
class IsGovernmentAgent(permissions.BasePermission):
"""Permite acesso apenas para agentes governamentais"""
def has_permission(self, request, view):
return request.user and request.user.is_government_agent
Proteção de Dados
Validação e Sanitização
Validação de Dados Sensíveis:
# validators.py
import re
from django.core.exceptions import ValidationError
def validate_cpf(value):
"""Valida CPF brasileiro"""
# Remove caracteres não numéricos
cpf = re.sub(r'\D', '', value)
if len(cpf) != 11:
raise ValidationError('CPF deve conter 11 dígitos')
# Verifica se todos os dígitos são iguais
if cpf == cpf[0] * 11:
raise ValidationError('CPF inválido')
# Calcula o primeiro dígito verificador
soma = sum(int(cpf[i]) * (10 - i) for i in range(9))
digito1 = 11 - (soma % 11)
if digito1 >= 10:
digito1 = 0
# Calcula o segundo dígito verificador
soma = sum(int(cpf[i]) * (11 - i) for i in range(10))
digito2 = 11 - (soma % 11)
if digito2 >= 10:
digito2 = 0
# Verifica os dígitos verificadores
if cpf[-2:] != f"{digito1}{digito2}":
raise ValidationError('CPF inválido')
return cpf
def sanitize_input(text):
"""Remove caracteres perigosos de entrada de texto"""
if not text:
return text
# Remove tags HTML/JavaScript
text = re.sub(r'<[^>]*>', '', text)
text = re.sub(r'javascript:', '', text, flags=re.IGNORECASE)
# Remove caracteres de controle
text = ''.join(char for char in text if ord(char) >= 32)
return text.strip()
Criptografia de Senhas
Configuração Django:
# settings.py
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 8,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
Segurança da API
Rate Limiting
Implementação com Django Ratelimit:
# views.py
from django_ratelimit.decorators import ratelimit
from rest_framework.decorators import api_view
@api_view(['POST'])
@ratelimit(key='ip', rate='5/m', method='POST') # 5 tentativas por minuto
def login(request):
"""Endpoint de login com rate limiting"""
# Lógica de autenticação
pass
@api_view(['GET'])
@ratelimit(key='user', rate='100/h') # 100 requisições por hora para usuários autenticados
def list_jobs(request):
"""Listagem de vagas com rate limiting"""
# Lógica de listagem
pass
Proteção CSRF
# settings.py
CSRF_COOKIE_SECURE = True # Apenas HTTPS em produção
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_TRUSTED_ORIGINS = [
'https://portal-talentos.gov.br',
'https://www.portal-talentos.gov.br',
]
# Em produção
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'
Headers de Segurança
# middleware.py
class SecurityHeadersMiddleware:
"""Adiciona headers de segurança às respostas"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# Headers de segurança
response['X-Content-Type-Options'] = 'nosniff'
response['X-Frame-Options'] = 'DENY'
response['X-XSS-Protection'] = '1; mode=block'
response['Referrer-Policy'] = 'strict-origin-when-cross-origin'
# HSTS em produção
if not settings.DEBUG:
response['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
return response
Logs e Auditoria
Sistema de Logs
# logging_config.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'security': {
'format': '{asctime} SECURITY [{levelname}] {message}',
'style': '{',
},
},
'handlers': {
'security_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/portal_talentos/security.log',
'maxBytes': 1024 * 1024 * 10, # 10 MB
'backupCount': 10,
'formatter': 'security',
},
'audit_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/portal_talentos/audit.log',
'maxBytes': 1024 * 1024 * 10, # 10 MB
'backupCount': 30,
'formatter': 'verbose',
},
},
'loggers': {
'security': {
'handlers': ['security_file'],
'level': 'INFO',
'propagate': False,
},
'audit': {
'handlers': ['audit_file'],
'level': 'INFO',
'propagate': False,
},
},
}
Auditoria de Ações
# audit.py
import logging
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.dispatch import receiver
audit_logger = logging.getLogger('audit')
security_logger = logging.getLogger('security')
@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
"""Registra login bem-sucedido"""
audit_logger.info(
f"Login successful - User: {user.email}, "
f"IP: {get_client_ip(request)}, "
f"User-Agent: {request.META.get('HTTP_USER_AGENT')}"
)
@receiver(user_login_failed)
def log_user_login_failed(sender, credentials, request, **kwargs):
"""Registra tentativa de login falhada"""
security_logger.warning(
f"Login failed - Username: {credentials.get('username')}, "
f"IP: {get_client_ip(request)}, "
f"User-Agent: {request.META.get('HTTP_USER_AGENT')}"
)
def get_client_ip(request):
"""Obtém o IP real do cliente"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
Conformidade LGPD
Implementações para LGPD
# lgpd_compliance.py
from django.db import models
from django.utils import timezone
class ConsentRecord(models.Model):
"""Registro de consentimento LGPD"""
user = models.ForeignKey('accounts.CustomUser', on_delete=models.CASCADE)
consent_type = models.CharField(max_length=50)
granted_at = models.DateTimeField(default=timezone.now)
revoked_at = models.DateTimeField(null=True, blank=True)
ip_address = models.GenericIPAddressField()
user_agent = models.TextField()
class Meta:
db_table = 'lgpd_consent_records'
class DataExportRequest(models.Model):
"""Solicitações de exportação de dados (LGPD)"""
user = models.ForeignKey('accounts.CustomUser', on_delete=models.CASCADE)
requested_at = models.DateTimeField(default=timezone.now)
completed_at = models.DateTimeField(null=True, blank=True)
file_url = models.URLField(null=True, blank=True)
status = models.CharField(max_length=20, default='pending')
class Meta:
db_table = 'lgpd_data_export_requests'
class DataDeletionRequest(models.Model):
"""Solicitações de exclusão de dados (direito ao esquecimento)"""
user_email = models.EmailField() # Mantém email para registro
requested_at = models.DateTimeField(default=timezone.now)
processed_at = models.DateTimeField(null=True, blank=True)
status = models.CharField(max_length=20, default='pending')
class Meta:
db_table = 'lgpd_data_deletion_requests'
Segurança em Desenvolvimento Futuro
Melhorias Planejadas
Autenticação Multi-Fator (MFA):
- Implementação de TOTP (Time-based One-Time Password)
- Suporte a aplicativos autenticadores
- Códigos de backup para recuperação
Monitoramento Avançado:
- Sistema de detecção de intrusão
- Análise comportamental de usuários
- Alertas em tempo real para atividades suspeitas
Criptografia Aprimorada:
- Criptografia de campos sensíveis no banco de dados
- Tokenização de CPF e dados pessoais
- Gerenciamento de chaves com rotação automática
Integração com Serviços Governamentais:
- Autenticação via Gov.br (OAuth 2.0)
- Validação de CPF com Receita Federal
- Integração com certificados digitais
Resposta a Incidentes
Procedimento Básico
- Detecção: Identificação através de logs e monitoramento
- Contenção: Isolamento do problema para evitar propagação
- Investigação: Análise da causa e extensão do incidente
- Remediação: Correção da vulnerabilidade
- Recuperação: Restauração dos serviços
- Documentação: Registro detalhado e lições aprendidas
Contatos de Emergência
# security_contacts.py
SECURITY_TEAM = {
'email': 'security@portal-talentos.gov.br',
'phone': '+55 11 xxxx-xxxx',
'escalation': 'ciso@portal-talentos.gov.br'
}
# Configuração de alertas automáticos
SECURITY_ALERTS = {
'critical': ['security@portal-talentos.gov.br', 'ops@portal-talentos.gov.br'],
'high': ['security@portal-talentos.gov.br'],
'medium': ['security@portal-talentos.gov.br'],
}
A segurança é um processo contínuo. Este documento reflete as implementações atuais e o roadmap de melhorias. Auditorias regulares e atualizações são essenciais para manter o sistema seguro.
O sistema está em desenvolvimento ativo. Nem todas as medidas de segurança estão completamente implementadas. As configurações de produção serão mais restritivas que o ambiente de desenvolvimento.