跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何限制未登录用户访问 Django 项目中的受保护页面

本文介绍如何使用 Django 的 @login_required 装饰器,强制所有敏感页面(如书籍详情、书单列表等)仅对已登录用户开放,彻底防止通过 URL 直接访问导致的权限绕过问题。 本文介绍如何使用 django 的 `@login_required` 装饰器,强制所有敏感页面(如书籍详情、书单列表等)仅对已登录用户开放,彻底防止通过 url 直接访问导致的权限绕过问题。 在当前的 Django 项目中,虽然已实现登录逻辑(signin 视图处理认证),但所有视图函数(如 index、get_book、get_books 等)均未进行访问控制校验。这导致用户无需登录即可通过直接输入 URL(例如 /books 或 /book/5)访问全部内容,严重违反权限最小化原则。 解决该问题最标准、最可靠的方式是使用 Django 内置的 @login_required 装饰器。它会自动拦截未认证请求,并重定向至登录页(默认为 /accounts/login/)。你需要首先确保 settings.py 中已正确配置登录重定向路径:
# settings.py LOGIN_URL = 'store:signin' # 指向你的登录视图名称 LOGIN_REDIRECT_URL = 'store:index' # 登录后跳转首页
接着,在所有需登录才能访问的视图函数上方添加装饰器。注意: index 视图作为首页必须受保护 (当前却被设为登录入口,逻辑矛盾),而 signin、registration、signout 等认证相关视图则 不应加装饰器 (否则将陷入重定向死循环)。 ✅ 正确改造示例(修改 views.py): go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载
from django.contrib.auth.decorators import login_required from django.contrib.auth import authenticate, login, logout from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from .models import Category, Writer, Book, Review, Slider from .forms import RegistrationForm, ReviewForm # ✅ 登录页:不加装饰器(允许匿名访问) def signin(request): if request.user.is_authenticated: return redirect('store:index') if request.method == "POST": user = request.POST.get('user') password = request.POST.get('pass') auth = authenticate(request, username=user, password=password) if auth is not None: login(request, auth) return redirect('store:index') else: messages.error(request, '用户名或密码错误') return render(request, "store/login.html") # ✅ 注册页:不加装饰器 def registration(request): form = RegistrationForm(request.POST or None) if form.is_valid(): form.save() return redirect('store:signin') return render(request, 'store/signup.html', {"form": form}) # ✅ 退出登录:不加装饰器(但建议 POST 验证 CSRF) def signout(request): logout(request) return redirect('store:index') # ✅ 首页(原 index):必须加 @login_required! @login_required def index(request): newpublished = Book.objects.order_by('-created')[:15] slide = Slider.objects.order_by('-created')[:3] context = { "newbooks": newpublished, "slide": slide } return render(request, 'store/index.html', context) # ✅ 所有业务页面均需保护 @login_required def get_book(request, id): # ...(原有逻辑保持不变) book = get_object_or_404(Book, id=id) # 注意:此处可进一步校验用户权限(如仅作者可编辑),但基础认证已由装饰器保障 # ... @login_required def get_books(request): books_ = Book.objects.all().order_by('-created') paginator = Paginator(books_, 10) page = request.GET.get('page') books = paginator.get_page(page) return render(request, "store/category.html", {"book": books}) @login_required def get_book_category(request, id): book_ = Book.objects.filter(category_id=id) paginator = Paginator(book_, 10) page = request.GET.get('page') book = paginator.get_page(page) return render(request, "store/category.html", {"book": book}) @login_required def get_writer(request, id): wrt = get_object_or_404(Writer, id=id) book = Book.objects.filter(writer_id=wrt.id) return render(request, "store/writer.html", {"wrt": wrt, "book": book})
⚠️ 重要注意事项: @login_required 默认重定向到 /accounts/login/,若你的登录 URL 是 store:signin,务必在 settings.py 中显式设置 LOGIN_URL = 'store:signin'; 装饰器 必须放在 def 语句正上方 ,且不能与 @csrf_protect 等其他装饰器顺序冲突(Django 会自动处理 CSRF,通常无需手动加); 若需更细粒度控制(如区分管理员/普通用户),应结合 User.is_staff、自定义权限或 @user_passes_test; 前端导航栏中,建议动态渲染登录/登出链接(利用 request.user.is_authenticated),提升用户体验。 通过以上改造,任何未登录用户尝试访问 /books、/book/1 等路径时,将被自动重定向至登录页,从根本上堵住 URL 直接访问的安全漏洞,符合 Django 官方推荐的最佳实践。

相关文章