我做了一个中间件,如果用户没有经过身份验证,但在登录后返回403 Forbidden,每次刷新页面我都登录,然后注销,等等。
这只发生在运行Gunicorn和Nginx的Ubuntu DigitalOcean droplet的生产环境中。
middleware.py
from django.shortcuts import render
def IsAuthMiddleware(get_response):
def middleware(request):
if (request.path.startswith('/dashboard') or 'account' in request.path) and not request.user.is_authenticated():
context = {
"title": "Not logged in",
"message": "- You are not logged in."
}
return render(request, '403.html', context)
response = get_response(request)
if response.status_code == 403:
res = render(request, '403.html', {'message': response.content.decode()})
res.status_code = 403
return res
if response.status_code == 404:
res = render(request, '404.html', {'message': response.content.decode()})
res.status_code = 404
return res
return response
return middleware
views.py
from django.shortcuts import render
from .models import Message
from dashboard.models import Subscriber, Newsletter, Unsubscription
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.utils import IntegrityError
from django.http import HttpResponseNotFound
from django.core.validators import validate_email
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
# Create your views here.
def index(request):
context = {
"title": "Home",
}
return render(request, 'main/index.html', context)
def privacy(request):
return render(request, 'main/privacy.html')
def contact(request):
if request.method == "POST":
context = {
"title": "Contact",
"msg": True,
"good": True,
"msg_content": "Your message has been sent and we will get back to you asap."
}
for _, item in request.POST.items():
if item == '':
context['good'] = False
context['msg_content'] = "Please fill in every input"
return render(request, 'main/contact.html', context)
msg = Message(
title = request.POST['title'],
email = request.POST['email'],
content = request.POST['content']
)
msg.save()
return render(request, 'main/contact.html', context)
else:
context = {
'title': 'Contact',
}
return render(request, 'main/contact.html', context)
def sub(request, id):
try:
newsletter = Newsletter.objects.get(id=id)
except ObjectDoesNotExist:
return HttpResponseNotFound('- requested newsletter does not exist')
context = {
'title': f'Subscribe to {newsletter.name}',
'msg': False,
'newsletter': newsletter
}
if request.method == 'POST':
fname = request.POST['fname']
lname = request.POST['lname']
email = request.POST['subemail']
try:
validate_email(email)
except ValidationError:
context['msg'] = True
context['msg_content'] = 'Email is not valid'
return render(request, 'main/sub.html', context)
sub = Subscriber(first_name=fname, last_name=lname, email=email, subscription=newsletter)
try:
sub.save(confirm=True)
except IntegrityError:
context['msg'] = True
context['msg_content'] = 'Email is already subscribed'
return render(request, 'main/sub.html', context)
context['title'] = context['title'].replace('Subscribe', 'Subscribed')
context['subscriber'] = sub
return render(request, 'main/subbed.html', context)
return render(request, 'main/sub.html', context)
def unsub(request, id):
try:
n = Newsletter.objects.get(id=id)
except ObjectDoesNotExist:
return HttpResponseNotFound('- newsletter does not exist')
context = {
'title': f'Unsubscribe from {n.name}',
'msg': False,
'newsletter': n
}
if request.method == "POST":
email = request.POST['unsubemail']
try:
validate_email(email)
except ValidationError:
context['msg'] = True
context['msg_content'] = 'Email is not valid'
return render(request, 'main/unsub.html', context)
try:
sub = Subscriber.objects.get(email=email, subscription=n)
except ObjectDoesNotExist:
context['msg'] = True
context['msg_content'] = 'Email is not subscribed'
return render(request, 'main/unsub.html', context)
if not sub.is_recv:
context['msg'] = True
context['msg_content'] = 'Email is not subscribed'
return render(request, 'main/unsub.html', context)
unsub = Unsubscription(subscription=n, prev=sub)
unsub.save()
sub.delete()
context['unsub'] = unsub
return render(request, 'main/unsubbed.html', context)
return render(request, 'main/unsub.html', context)
@csrf_exempt
def signupconfirm(request):
if request.method == "POST":
sub = Subscriber.objects.get(id=int(request.POST['id']))
sub.is_recv = True
sub.consent_date = timezone.now()
sub.save()
context = {
'title': f'Successfully signed up to {sub.subscription.name}',
'subscriber': sub,
'validated': True
}
return render(request, 'main/subbed.html', context)
return HttpResponseNotFound('no origin')
我尝试使用不同的会话引擎,但没有一个工作和is_authenticated不断变化。
页面上是否隐藏了退出登录的url ?
按钮用这个href代替{% url 'logout' %}
href="javascript:{document.getElementById('logout').submit()}"
然后将此表单放在页面的某个位置。
<form id="logout" method="POST" action="{% url 'logout' %}">
{% csrf_token %}
<input type="hidden" />
</form>
它现在可能与新版本的django排序,但我记得我不得不在我的主页上这样做,因为类似的事情。
你也可以在django自己的装饰器中使用login_required。我以前没有做过太多的中间件,但希望能帮助你。
from django.contrib.auth.decorators import login_required
@login_required
def your_view_name(request):
....