Resolvi falar disso porque vi pela internet que isso é uma questão bem recorrente para quem desenvolve em
Python com
Django. A forma "normal" de servir arquivos seria declarando o MEDIA_ROOT no seu
settings.py e adicionando a rota em
urls.py, certo?
Bom, isso funciona, mas qualquer um pode acessar os arquivos lá. Digamos que sua pasta MEDIA fosse "uploads" e houvesse um arquivo com o nome "user_profile1_image.png", então QUALQUER UM que digitasse no navegador http://<seu domínio ou ip>/uploads/user_profile1_image.png veria a imagem. Quando se lida com arquivos sensíveis, isso não é nada bom.
Como resolver isso?
Primeiramente, existem várias formas de se resolver essa questão. A maioria delas vai deixar o serviço por conta do Django. Mas além de aumentar o tamanho do código, pode também sobrecarregar o servidor, a depender. Em vez disso, você pode usar o seu próprio servidor para isso, de um jeito bem fácil, aliás. Aqui mostrarei como usar o Nginx para isso, mas é possível fazer algo parecido com o Apache também.
Mão na massa!
É bem simples. Siga até o arquivo de configuração do
Nginx, em que o seu servidor foi configurado. Provavelmente...
nano /etc/nginx/sites-enabled/SEU_PROJETO
...deve te levar até lá. Você agora só precisa adicionar no bloco "server" o seguinte:
location /ARQUIVOS/ {
internal;
root /home/USER/PROJETO;
}
Onde ARQUIVOS é o nome da pasta a ser protegida e root /home/USER/PROJETO; é o caminho COMPLETO até a pasta raiz do seu projeto. Salve e feche.
Não é preciso fazer nada em settings.py, não adicione a pasta como MEDIA_ROOT e se você já fez isso, retire essa configuração.
Em urls.py crie uma rota para uma view como qualquer outra. Como exemplo,
urlpatterns = [
...,
path('file/', require_files),
...
]
Em views.py do app que vai consumir esses arquivos, crie a função:
def require_files(request):
if request.user.is_staff:
response = HttpResponse(status=200)
response['Content-Type'] = ""
response['X-Accel-Redirect'] = request.path
return response
Perceba que alteramos o cabeçalho da resposta. É exatamente essa alteração que permite ao Nginx saber se deve ou não servir determinado arquivo. Nesse caso, apenas o pessoal da staff poderá acessá-los, mas com essa lógica você tem total liberdade para controlar a view que dará permissão de acesso como você bem quiser.
Por exemplo, se existe o model Pedido com um arquivo enviado pelo usuário e ele queira acessar, a sua view seria algo parecido com isso:
@login_required(login_url="/login/")
def require_files(request, id):
# Isso limitará a pesquisa ao usuário então se ele der um jeito de mandar o id de um pedido de outro usuário
# será negado
pedido = Pedido.objects.filter(id=id,user_id=request.user.id)
# Garante que o pedido existe
if pedido:
response = HttpResponse(status=200)
response['Content-Type'] = ""
response['X-Accel-Redirect'] = '/' + pedido[0].arquivo
return response
É isso, pessoal, até mais!
Nenhum comentário foi encontrado.