Django Rest API多密码登录:账户级登录实现方法咨询
嘿,针对你要实现的账户级登录需求,结合你现有的Django模型结构,我给你梳理一套可行的实现方案,咱们一步步来:
实现账户级登录的具体步骤
默认Django认证是基于User模型的,咱们需要自定义认证逻辑,让系统支持用Account的账号名和密码登录,同时严格限制后续的数据访问范围。
1. 自定义认证后端
首先创建一个自定义认证后端,让它能验证Account的密码,并返回对应的Account实例。在你的app下新建backends.py文件:
from django.contrib.auth.backends import BaseBackend from .models import Account class AccountAuthBackend(BaseBackend): def authenticate(self, request, account_name=None, password=None, **kwargs): try: # 根据账户名找到对应的Account记录 account = Account.objects.get(account_name=account_name) # 注意:这里要替换成你实际的密码解密逻辑 # 比如你封装的解密方法 account.decrypt_password() if account.decrypt_password() == password: return account except Account.DoesNotExist: return None def get_user(self, user_id): # 这里的user_id是Account的主键ID try: return Account.objects.get(pk=user_id) except Account.DoesNotExist: return None
然后在项目的settings.py中配置认证后端,同时保留默认的User认证(方便兼容原有登录逻辑):
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'your_app_name.backends.AccountAuthBackend', # 替换成你的app名称 ]
2. 编写账户登录视图
接下来写一个专门的登录视图,接收account_name和password参数,调用自定义后端完成认证:
from django.contrib.auth import login, authenticate from django.shortcuts import render, redirect from django.contrib import messages def account_login(request): if request.method == 'POST': account_name = request.POST.get('account_name') password = request.POST.get('password') # 使用自定义后端进行认证 account = authenticate(request, account_name=account_name, password=password) if account is not None: # 登录成功,此时request.user就是当前的Account实例 login(request, account) return redirect('account_dashboard') # 跳转到账户专属页面 else: messages.error(request, "账户名或密码错误,请重试") return render(request, 'account_login.html')
对应的登录模板account_login.html可以这样写:
<form method="post"> {% csrf_token %} <div> <label>账户名:</label> <input type="text" name="account_name" required> </div> <div> <label>密码:</label> <input type="password" name="password" required> </div> <button type="submit">登录账户</button> </form>
3. 控制数据访问范围
登录成功后,必须确保用户只能访问当前登录Account的关联数据,这里分两种常见场景处理:
场景1:普通Django视图(函数/CBV)
函数视图示例:
from django.contrib.auth.decorators import login_required from .models import Transaction @login_required def account_dashboard(request): # 当前登录的Account实例 current_account = request.user # 只查询该Account下的交易记录 transactions = Transaction.objects.filter(account=current_account) return render(request, 'account_dashboard.html', {'transactions': transactions})
类视图(CBV)示例:
from django.views.generic import ListView from django.contrib.auth.mixins import LoginRequiredMixin from .models import Transaction class TransactionListView(LoginRequiredMixin, ListView): model = Transaction template_name = 'transaction_list.html' def get_queryset(self): # 重写查询集,只返回当前Account的交易 return Transaction.objects.filter(account=self.request.user)
场景2:Django REST Framework接口
如果是API接口,在视图集中过滤数据:
from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from .models import Transaction, Account from .serializers import TransactionSerializer, AccountSerializer class AccountViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] serializer_class = AccountSerializer def get_queryset(self): # 只返回当前登录的Account return Account.objects.filter(id=self.request.user.id) class TransactionViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] serializer_class = TransactionSerializer def get_queryset(self): # 只返回当前Account关联的交易 return Transaction.objects.filter(account=self.request.user)
4. 关键注意事项
- 用户类型判断:因为自定义认证返回的是
Account实例,所以request.user不再是默认的User对象。如果需要同时兼容原有User登录逻辑,可以在视图中判断类型:from django.contrib.auth.models import User def some_view(request): if isinstance(request.user, User): # 处理User登录场景,返回该用户关联的所有Account accounts = request.user.account_set.all() else: # 处理Account登录场景,返回当前Account accounts = [request.user] - 密码安全:确保你的
EncryptedTextField加密解密逻辑是安全的,避免明文处理密码。 - 全局权限控制:所有关联
Account的模型查询,都要加上过滤条件,防止越权访问。
内容的提问来源于stack exchange,提问作者dinesh balan
相关产品推荐
相关产品推荐

