Python Django中间件,具有登录名和密码,可隐藏所有网站页面
我编写了以下中间件,它呈现表单并要求用户登录和密码。中间件应应用于整个网站:Python Django中间件,具有登录名和密码,可隐藏所有网站页面,python,django,middleware,Python,Django,Middleware,我编写了以下中间件,它呈现表单并要求用户登录和密码。中间件应应用于整个网站: class InviteLoginForWebsiteMiddleware(object): def process_request(self, request): if request.session.get('has_invite') == True: return None form = WebsiteLoginForm() ex
class InviteLoginForWebsiteMiddleware(object):
def process_request(self, request):
if request.session.get('has_invite') == True:
return None
form = WebsiteLoginForm()
extra_context = dict()
extra_context['form'] = form
template_name = 'websiteLogin.html'
if request.method == "POST":
form = WebsiteLoginForm(request.POST)
if form.is_valid():
login = form.cleaned_data['login']
password = form.cleaned_data['password']
if login == "mylogin" and password == "mypassword":
request.session['has_inv'] = True
return None
return ExtraContextTemplateView.as_view(template_name=template_name, extra_context=extra_context)(request)
此解决方案的问题是,当我在进程内创建表单时,呈现页面上缺少请求csrf令牌。我一直在寻找答案,发现开发人员建议生成表单并在process_视图中处理它
将所有代码移动到process_视图后,如:
代码开始工作,生成了csrf令牌,我可以提交带有登录名和密码的表单
当用户进入无效页面(如www.mysite.com/notworkingurl/)时,就会出现问题。在这种情况下,process_视图不工作,出现404错误,用户被重定向到部分显示web应用程序界面的页面。当然,我希望中间件应该隐藏应用程序的所有页面
再一次:
class ExtraContextTemplateViewCsrfProtect(TemplateView):
extra_context = None
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super(ExtraContextTemplateViewCsrfProtect, self).dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
context = super(ExtraContextTemplateViewCsrfProtect, self).get_context_data(*args, **kwargs)
if self.extra_context:
context.update(self.extra_context)
return context
post = TemplateView.get
也许您可以尝试使用登录所需的中间件:
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
settings.py:
LOGIN_URL = '/login/'
LOGIN_EXEMPT_URLS = (
r'^about\.html$',
r'^legal/', # allow any URL under /legal/*
)
MIDDLEWARE_CLASSES = (
# ...
'python.path.to.LoginRequiredMiddleware',
)
登录所需的中间件:
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
您的中间件不仅缺少csrf令牌,而且容易受到csrf攻击 如果要使用此模式,而不是重定向到单个登录视图,则应将所有表单逻辑移到实际视图中。然后,您可以使用
csrf\u protect
保护视图免受csrf攻击,这也使您能够使用模板中的令牌:
class InviteLoginForWebsiteMiddleware(object):
def process_request(self, request):
if request.session.get('has_invite') == True:
return None
return csrf_protect(CustomLoginView.as_view())(request)
但是,我建议采用matox建议的方法 您是否将404请求重定向到
进程视图
?否,我有自定义URL,在引发404异常时重定向到404视图。当我的中间件代码在“process\u view”中工作时,用户输入的url不正确,终端视图不存在,并且引发404。这很奇怪。流程视图的哪一行引发了404异常?我编辑了我之前的答案。请看一看!显示的进程视图不会引发任何异常,但当用户输入不正确的url时,会再次发生异常。谢谢!我也在我的应用程序中使用它。但如果我要玩它,那么我必须打开至少一个在我的应用程序中创建帐户的可能性。这不是我想要的。我正在寻找一种可以在需要时轻松打开或关闭的add-hoc解决方案。您可以通过注释中间件类
中的中间件来轻松关闭它。是的,这也是正确的,就像任何其他中间件一样。您可以根据自己的情况替换请求.用户
。这个函数只是将任何未经授权的请求重定向到您的登录页面。我相信这就是你本质上需要的。这里的问题是,我必须提供访问帐户的功能,所以基本上,用户应该能够创建配置文件,修改它们等等。这个功能已经在网站上展示了,但我不想重构代码。在这种情况下,整个应用程序的简单包装将更适合。同时,你的解决方案更专业、更稳健。是的,你是对的。它将非常容易受到攻击,但在我的情况下,这将是好的,因为,正如我写给matox的,这将是唯一的添加临时解决方案,以隐藏网站的第一次与能力,打开或关闭它的时间。如果直接使用您的代码,那么它不起作用,但是如果修改它并将csrf_protect移动到我的TemplateView中,那么问题就解决了。