使用JWT实现Django经销商账户身份认证的可行方案求助
经销商JWT身份认证落地方案
注意:你当前
Distributors模型中password字段为明文存储,存在严重安全隐患,方案第一步会优先改造密码存储逻辑。
1. 改造Distributors模型,新增密码加解密方法
修改后的模型代码如下:
from django.contrib.auth.hashers import make_password, check_password from django.db import models # 你的其他依赖导入如TimeStampedModel、BRCPFField等 class Distributors(TimeStampedModel): name = models.CharField("Nome completo", max_length=250) cpf = BRCPFField("CPF") email = models.EmailField("Email") # 原长度15无法存储加密后的密码,修改为128位 password = models.CharField("Senha", max_length=128) def __str__(self): return self.name # 新增:密码加密存储方法,创建经销商账号时必须调用 def set_password(self, raw_password): self.password = make_password(raw_password) # 新增:密码校验方法,登录逻辑会调用 def check_password(self, raw_password): return check_password(raw_password, self.password)
修改完成后执行Django迁移命令同步表结构,存量明文密码需要批量调用set_password方法完成加密。
正确创建经销商账号示例:
distributor = Distributors( name="测试经销商", cpf="对应CPF编码", email="xxx@test.com" ) distributor.set_password("用户设置的明文密码") # 必须调用该方法加密密码 distributor.save()
2. 自定义经销商认证后端
在APP目录下新建backends.py文件,适配Distributors表的认证逻辑:
from django.contrib.auth.backends import BaseBackend from .models import Distributors class DistributorAuthBackend(BaseBackend): def authenticate(self, request, name=None, password=None, **kwargs): if not name or not password: return None try: distributor = Distributors.objects.get(name=name) except Distributors.DoesNotExist: return None # 校验密码 if distributor.check_password(password): return distributor return None def get_user(self, user_id): try: return Distributors.objects.get(pk=user_id) except Distributors.DoesNotExist: return None
修改项目settings.py,新增认证后端配置:
AUTHENTICATION_BACKENDS = [ # 保留默认Django用户认证后端,不影响原有超级用户的登录逻辑 'django.contrib.auth.backends.ModelBackend', # 新增经销商认证后端,替换为你自己的实际文件路径 '你的APP名称.backends.DistributorAuthBackend', ]
3. 自定义JWT登录视图,适配name+password校验规则
本方案基于djangorestframework-simplejwt(Django生态最常用的JWT库)实现,自定义登录序列化器和视图:
from rest_framework import serializers from rest_framework_simplejwt.views import TokenObtainPairView from .backends import DistributorAuthBackend class DistributorTokenSerializer(serializers.Serializer): name = serializers.CharField(required=True) password = serializers.CharField(required=True, write_only=True) def validate(self, attrs): name = attrs.get('name') password = attrs.get('password') # 调用自定义认证后端校验身份 distributor = DistributorAuthBackend().authenticate( request=self.context.get('request'), name=name, password=password ) if not distributor: raise serializers.ValidationError('用户名或密码错误') # 生成JWT token refresh = TokenObtainPairView.get_token(distributor) return { 'refresh': str(refresh), 'access': str(refresh.access_token), 'distributor_name': distributor.name, 'email': distributor.email } class DistributorTokenObtainView(TokenObtainPairView): serializer_class = DistributorTokenSerializer
4. 配置登录路由
修改APP的urls.py,新增经销商登录接口路由:
from django.urls import path from .views import DistributorTokenObtainView urlpatterns = [ # 经销商登录获取token接口 path('api/distributor/login/', DistributorTokenObtainView.as_view(), name='distributor_login'), # 其他原有路由 ]
5. 接口权限校验配置
修改项目settings.py,配置REST框架默认认证类:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ) }
后续需要校验经销商登录状态的接口,只需添加权限类permission_classes = [IsAuthenticated],即可正常校验身份,request.user会直接返回对应的Distributors对象。
内容的提问来源于stack exchange,提问作者afonso
相关产品推荐
相关产品推荐

