Django 之login_required的知识点
在进行页面登录验证优化时,想到了用户验证登录和登出及限流功能,在添加用户登录调用@login_required时,访问/login自动跳转到/accounts/login/,这个路由又没有定义就是显示404状态码。
作为一个新入门的学习者首先是排查路由配置、视图、去掉验证@login_required验证发现是@login_required的跳转定义问题,在没有定义的情况下默认跳转路径就是/accounts/login/,这下就破案了。
接下来,就是找解决方案,搜一下@login_required验证失败重定向的配置即可。
路由配置
from django.contrib import admin
from django.urls import path, include
from myapp.views import *
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', login_view, name='login'),
path('logout/', user_logout, name='logout'),
path('captcha/', include('captcha.urls')),
path('upload/', upload_file, name='upload'),
]
视图配置
from django.contrib import messages
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url
from django.shortcuts import redirect
#添加用户登录视图和注销视图:
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
import paramiko
import tempfile
def login_view(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
captcha_solution = request.POST.get('captcha_solution')
captcha_key = request.POST.get('captcha_key')
# 验证码校验
if captcha_key and captcha_solution:
if not CaptchaStore.objects.filter(response=captcha_solution, hashkey=captcha_key).exists():
messages.error(request, '验证码错误')
return redirect('login')
# 身份验证
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
return redirect('upload')
else:
messages.error(request, '用户名或密码错误')
return redirect('login')
new_key = CaptchaStore.generate_key()
image_url = captcha_image_url(new_key)
return render(request, 'login.html', {'key': new_key, 'image_url': image_url})
@login_required
def user_logout(request):
logout(request)
messages.info(request,'退出登录')
return redirect('login')
#定义限流装饰器
from django.core.cache import cache
from django.http import HttpResponseForbidden
def rate_limit(limit_count):
def decorator(view_func):
def wrapper(request, *args, **kwargs):
# 获取当前用户
user = request.user
# 检查该用户的访问次数
cache_key = f'rate_limit:{user.username}'
access_count = cache.get(cache_key, 0)
# 如果访问次数超过限制,返回 403 Forbidden
if access_count >= limit_count:
# logging.error('用户 {} 查看上传文件列表失败'.format(request.user.username, datetime.now()))
return HttpResponseForbidden('访问次数超过限制')
# 增加访问次数并设置缓存时间为 1 分钟
cache.set(cache_key, access_count + 1, 60)
# 继续执行视图函数
return view_func(request, *args, **kwargs)
return wrapper
return decorator
#上传视图
@login_required
def upload_file(request):
if request.method == 'POST':
file = request.FILES.get('file')
if file:
# 连接远程服务器
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# ssh.connect('remote_server_ip', username='username', password='password')
ssh.connect('10.0.0.127', username='root', password='123456')
try:
# 创建临时文件
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
# 将上传的文件内容写入临时文件
for chunk in file.chunks():
temp_file.write(chunk)
temp_file.seek(0) # 将文件指针移动到文件开头
# 上传临时文件到远程服务器的/data目录
sftp = ssh.open_sftp()
#使用用户密码/秘钥连接
sftp.putfo(temp_file, '/home/yunwei/apache-jmeter-5.5/ProCase/scrpit/' + file.name)
sftp.close()
ssh.close()
messages.success(request, '文件上传成功')
return redirect('upload') # 重定向到上传页面
except Exception as e:
messages.error(request, '文件上传失败:{}'.format(str(e)))
else:
messages.error(request, '请选择要上传的文件')
return render(request, 'upload.html')
解决方案
在Django中,可以使用login_required装饰器来对视图函数进行登录验证。当用户没有登录时,装饰器会将用户重定向到默认的登录页面或者自定义的登录页面。 默认情况下,Django的login_required装饰器会将用户重定向到名为/accounts/login/的URL。如果你希望自定义登录跳转的URL,你可以在项目中进行相关配置。 首先,你需要在项目的URL配置文件(通常是urls.py)中定义一个URL来处理登录验证失败重定向的请求
from django.urls import path
from django.contrib.auth.views import LoginView
urlpatterns = [
path('my-login/', LoginView.as_view(), name='my_login'),
# other URLs
]
my-login/路由将被用于处理登录验证失败的跳转请求。LoginView是Django内置的登录视图,它会自动渲染一个登录页面。 接下来,你需要告诉Django在登录验证失败时应该重定向到哪个URL。你可以在项目的设置文件(通常是settings.py)中添加以下配置:
LOGIN_URL = '/my-login/'
在这个配置中,LOGIN_URL设置为/my-login/,即登录验证失败时应该重定向到my-login/路由。 通过以上配置,当使用login_required装饰器的视图函数登录验证失败时,用户将被重定向到my-login/路由,即自定义的登录页面。 请注意,login_required装饰器需要和Django的认证系统一起工作。你需要在项目中启用认证系统并配置相关认证后端和用户模型。