说真的每次分析源码,大多是迫不得已,实在是封装之后的函数我们没法直接使用当前的数据。但是应该和很多人一样,在我们最后分析源码之后,将数据正常返回,实现了项目功能的时候,还是很开心的。这就是
开发的魅力吧!
需求分析
用户登录,前后端提供的字段
前端
- username:用户名
- password:密码
- vercode:图片验证码
后端
- user:用户对象
- token:JWT生成的Token
分析
咋一看的时候,觉得还挺简单的,自定义一个返回的函数不就可以了嘛!
但是写完之后才发现,这个vercode
一直没有用过啊!
哦豁~~
图片验证码
图片验证码是用户按钮之后,想后端发送请求,后端生成图片验证码,然后将图片返回给前端的
同时,在后端设置session:将用户的请求的图片验证码的字符串保存到session中
这里session中的vercode怎么获取呢???
获取用户输入
前端在发送数据的时候,会将用户输入的图片验证码的值,直接发送到后台
对于这种比较特殊的数据,JWT肯定不会都给我们返回了
源码分析
DRF_JWT
# rest_framwork_jwt/views.py/82
class ObtainJSONWebToken(JSONWebTokenAPIView):
"""
API View that receives a POST with a user's username and password.
Returns a JSON Web Token that can be used for authenticated requests.
"""
serializer_class = JSONWebTokenSerializer
从这段代码我们可以看到 ObtainJSONWebToken 接收到POST请求后,会返回username 和 password
但是,是没有vercode的!
My_CODE
# 这段代码是关于DRF自定义的部分,还要在配置文件里面指定
def get_user_by_account(account):
"""选择自定义校验的用户信息"""
try:
user = User.objects.get(username=account) # 帐号为用户名
except User.DoesNotExist:
return None
else:
return user
class UsernameMobileAuthBackend(ModelBackend):
"""自定义用户认证"""
def authenticate(self, request, username=None, password=None, vercode=None, **kwargs):
current_code = kwargs.get("code") # 用户输入的图片验证码,
print("用户输入的图片验证码:", current_code)
user = get_user_by_account(username)
if user is not None and user.password == encrypt.md5(password):
return user
def jwt_response_payload_handler(token, user=None, request=None):
"""在这里修改用户登录后的配置信息"""
data = {
"code": 0
, "msg": "登入成功"
, "data": {
'user': user,
"access_token": token,
}
}
return data
从上面UsernameMobileAuthBackend的authenticate()中我们可以测试
在不修改的情况下,我们是获取不到request
,vercode
,kwargs
的
修改源码
当你看明白上面的原因和分析,我们可以想想
在request里面,我们连request.method都可以获取到,怎么可能获取不到前端提交的数据!!
从路由开始找!!!
其实找起来还是很快的:
url(r'^authorization/$', obtain_jwt_token, name="authorization"),
from rest_framework_jwt.views import obtain_jwt_token
obtain_jwt_token = ObtainJSONWebToken.as_view()
serializer_class = JSONWebTokenSerializer
这时候,我们进到JWT的序列化器
了,分析一下吧
def __init__(self, *args, **kwargs):
"""
Dynamically add the USERNAME_FIELD to self.fields.
"""
super(JSONWebTokenSerializer, self).__init__(*args, **kwargs)
self.fields[self.username_field] = serializers.CharField()
self.fields['password'] = PasswordField(write_only=True)
@property
def username_field(self):
return get_username_field()
def validate(self, attrs):
credentials = {
self.username_field: attrs.get(self.username_field),
'password': attrs.get('password'),
'code': self.initial_data["vercode"] # 添加vercode
}
这里为什么知道
self.initial_data里面有vercode
???
DeBUG大法
了解一下!!!
OK,这里修改好了之后,在获取的时候,直接添加一个默认参数verocde就可以了!
评论区