Estou trabalhando em um grande aplicativo Django, a grande maioria dos quais requer um login para acessar. Isso significa que em todo o nosso aplicativo espalhamos:
@login_required
def view(...):
Tudo bem e funciona muito bem , desde que nos lembremos de adicioná-lo em todos os lugares ! Infelizmente, às vezes esquecemos, e a falha muitas vezes não é terrivelmente evidente. Se o único link para uma visualização estiver em uma página @login_required, você provavelmente não perceberá que pode realmente acessar essa visualização sem fazer login. Mas os bandidos podem perceber, o que é um problema.
Minha ideia era reverter o sistema. Em vez de digitar @login_required em todos os lugares, eu teria algo como:
@public
def public_view(...):
Apenas para as coisas públicas. Tentei implementar isso com algum middleware e não consegui fazer funcionar. Tudo o que experimentei interagiu mal com outro middleware que estamos usando, eu acho. Em seguida, tentei escrever algo para percorrer os padrões de URL para verificar se tudo o que não é @public foi marcado como @login_required - pelo menos, obteríamos um erro rápido se esquecêssemos algo. Mas não consegui descobrir como saber se @login_required tinha sido aplicado a uma visualização ...
Então, qual é a maneira certa de fazer isso? Obrigado pela ajuda!
Respostas:
Middleware pode ser sua melhor aposta. Eu usei este trecho de código no passado, modificado de um snippet encontrado em outro lugar:
Em seguida, em settings.py, liste os URLs básicos que deseja proteger:
Desde que o seu site siga as convenções de URL para as páginas que requerem autenticação, este modelo funcionará. Se não for um ajuste individual, você pode escolher modificar o middleware para se adequar mais às suas circunstâncias.
O que eu gosto nessa abordagem - além de remover a necessidade de entupir a base de código com
@login_required
decoradores - é que, se o esquema de autenticação mudar, você terá um lugar para ir para fazer mudanças globais.fonte
@public
decorator, que define o_public
atributo na visualização e o middleware, em seguida, pula essas visualizações. O decorador csrf_exempt do Django funciona da mesma maneiraExiste uma alternativa para colocar um decorador em cada função de visualização. Você também pode colocar o
login_required()
decorador nourls.py
arquivo. Embora ainda seja uma tarefa manual, pelo menos você tem tudo em um só lugar, o que facilita a auditoria.por exemplo,
Observe que as funções de visualização são nomeadas e importadas diretamente, não como strings.
Observe também que isso funciona com qualquer objeto de exibição que pode ser chamado, incluindo classes.
fonte
No Django 2.1, podemos decorar todos os métodos em uma classe com:
ATUALIZAÇÃO: Eu também descobri que o seguinte funciona:
e definir
LOGIN_URL = '/accounts/login/'
em settings.pyfonte
É difícil mudar as suposições embutidas no Django sem retrabalhar a maneira como as urls são entregues para as funções de visualização.
Em vez de mexer nos componentes internos do Django, aqui está uma auditoria que você pode usar. Basta verificar cada função de visualização.
Execute-o e examine a saída para
def
s sem decoradores apropriados.fonte
Aqui está uma solução de middleware para django 1.10+
Os middlewares devem ser escritos de uma nova maneira no django 1.10+ .
Código
Instalação
Adicionar ao MIDDLEWARE
MIDDLEWARE = [... '.middleware.RequireLoginMiddleware', # Requer login]
Fontes:
Esta resposta de Daniel Naab
Tutorial do Django Middleware por Max Goodridge
Django Middleware Docs
fonte
__call__
, oprocess_view
gancho ainda é usado [editado]Inspirado pela resposta de Ber, escrevi um pequeno snippet que substitui a
patterns
função, envolvendo todos os retornos de chamada de URL com ologin_required
decorador. Isso funciona no Django 1.6.Usá-lo funciona assim (a chamada para
list
é necessária por causa doyield
).fonte
Você realmente não pode vencer isso. Você simplesmente deve fazer uma declaração dos requisitos de autorização. Onde mais você colocaria esta declaração, exceto ao lado da função view?
Considere substituir suas funções de visualização por objetos que podem ser chamados.
Você então transforma suas funções de visualização em subclasses de
LoginViewFunction
.Não salva nenhuma linha de código. E não ajuda o problema do "esquecemos". Tudo o que você pode fazer é examinar o código para ter certeza de que as funções de visualização são objetos. Da classe certa.
Mas mesmo assim, você nunca saberá realmente que todas as funções de visualização estão corretas sem um conjunto de testes de unidade.
fonte
def
's. Você pode escrever trivialmente um script muito curto para varrer todosdef
os módulos de visualização e determinar se um @login_required foi esquecido.urls.py
.Seria possível ter um único ponto de partida para todos os
urls
em uma espécie de include e que o decorasse usando este pacote https://github.com/vorujack/decorate_url .fonte
Existe um aplicativo que fornece uma solução plug-and-play para isso:
https://github.com/mgrouchy/django-stronghold
fonte