Django自定义认证Session漏洞:未授权访问与URL参数篡改问题
Django自定义认证系统权限漏洞修复
存在的问题
- 未登录用户直接输入类似
127.0.0.1/account/Adam的URL即可进入账户页面,即便该用户未在数据库注册,页面仍会显示对应欢迎信息。 - 用全局变量
auth = False控制权限的方案存在严重缺陷:已登录用户在同一会话中篡改URL末尾的用户名参数,就能显示任意用户名的欢迎信息;且全局变量为服务器共享,多用户登录时会互相干扰。
问题根源
- 全局变量不适合会话级状态管理:
auth是全局变量,所有访问服务器的用户共用该值,一个用户登录会将所有用户的auth设为True,完全无法实现用户隔离。 - 账户视图未做身份校验:
account视图直接将URL中的composterName传给模板,既不检查该用户是否存在,也不验证当前登录用户是否与该用户名匹配。 - 密码明文存储:注册时直接将密码存入数据库,属于严重安全隐患。
修复方案
1. 改用Django Session存储登录状态
Django自带的Session是会话级存储,每个用户拥有独立Session,是管理登录状态的正确方式。
2. 修改登录视图
验证用户密码正确后,将用户唯一标识存入Session,替代全局变量:
def login(request): if request.method == 'POST': email = request.POST['Email'] password = request.POST['Password'] try: user = Composter.objects.get(composterEmail=email) # 先暂时用明文验证,后续需替换为哈希验证 if user.composterPassword == password: # 将用户ID和用户名存入session request.session['user_id'] = user.id request.session['composter_name'] = user.composterName return redirect('account', composterName=user.composterName) else: messages.info(request, '密码错误') return redirect('login') except ObjectDoesNotExist: messages.info(request, '该邮箱未注册') return redirect('login') return render(request, 'users/login.html')
3. 修改账户视图
先检查Session是否存在登录用户,再验证URL中的用户名是否属于当前登录用户,同时确认用户存在:
def account(request, composterName): # 检查是否登录 user_id = request.session.get('user_id') if not user_id: return redirect('login') try: current_user = Composter.objects.get(id=user_id) # 验证URL中的用户名是否与当前登录用户一致 if current_user.composterName != composterName: messages.info(request, '无权访问该账户') return redirect('account', composterName=current_user.composterName) # 直接传递当前用户信息给模板,不依赖URL参数 return render(request, 'users/account.html', {'composterName': current_user.composterName}) except ObjectDoesNotExist: # Session中用户ID不存在时,清除Session并跳转登录 del request.session['user_id'] messages.info(request, '用户不存在') return redirect('login')
4. 修复密码存储问题(关键安全优化)
注册时使用Django的密码哈希函数存储密码,避免明文泄露:
# 先导入哈希工具 from django.contrib.auth.hashers import make_password, check_password def composter_register(request): if request.method == 'POST': # 其他字段获取代码不变 composterName = request.POST['Composter_Name'] composterEmail = request.POST['Composter_Email'] composterPassword = request.POST['Composter_Password'] composterConfirmationPassword = request.POST['Composter_Confirmation_Password'] composterAddress = request.POST['Composter_Address'] composterState = request.POST['Composter_State'] composterCity = request.POST['Composter_City'] composterZipCode = request.POST['Composter_Zip_Code'] if composterPassword == composterConfirmationPassword: if Composter.objects.filter(composterName=composterName).exists(): messages.info(request,'用户名已被占用!') return redirect('composter_register') elif Composter.objects.filter(composterEmail=composterEmail).exists(): messages.info(request,'邮箱已被注册!') return redirect('composter_register') else: # 哈希密码后存储 hashed_password = make_password(composterPassword) composter = Composter( composterName=composterName, composterEmail=composterEmail, composterPassword=hashed_password, composterAddress=composterAddress, composterState=composterState, composterCity=composterCity, composterZipCode=composterZipCode ) composter.save() messages.info(request,'注册成功,请登录') return redirect('login') else: messages.info(request,'两次输入的密码不一致!') return redirect('composter_register') else: return render(request, 'users/composter_register.html')
同时修改登录视图的密码验证逻辑,使用哈希校验:
# 登录视图中的密码验证部分替换为: if check_password(password, user.composterPassword): request.session['user_id'] = user.id request.session['composter_name'] = user.composterName return redirect('account', composterName=user.composterName) else: messages.info(request, '密码错误') return redirect('login')
5. 可选:添加登出功能
提供登出选项,清除当前用户的Session:
def logout(request): # 清除Session中的用户信息 request.session.flush() return redirect('home')
在urls.py中添加路由:
path('logout/', views.logout, name='logout')
额外建议
- 可以使用Django的
@login_required装饰器简化登录验证逻辑,若使用自定义用户模型,需配置AUTH_USER_MODEL或调整装饰器适配逻辑。 - 可移除账户URL中的用户名参数,直接从Session获取当前用户信息渲染页面,彻底避免URL篡改问题,例如将路由改为
path('account/', views.account, name='account'),视图直接使用Session内的用户数据。
内容的提问来源于stack exchange,提问作者Leo Narido
相关产品推荐
相关产品推荐

