您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django
【Vue+DRF生鲜电商】15.用户注册使用信号量实现密码加密
admin2019年5月4日 22:25 【Django | Vue 】 1307人已围观
Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。
### 密码加密保存 #### 重载create方法密码加密保存 所以在`UserSerializer`中重载`create(self, validated_data)`方法,添加以下代码 ```python class UserSerializer(serializers.ModelSerializer): # ... 省略代码 def create(self, validated_data): user = super(UserSerializer, self).create(validated_data=validated_data) # user对象是Django中继承的AbstractUser # UserProfile-->AbstractUser-->AbstractBaseUser中有个set_password(self, raw_password)方法 user.set_password(validated_data['password']) # 取出password密码,进行加密后保存 user.save() # ModelSerializer有一个save()方法,save()里面会调用create()函数,这儿重载了create()函数,加入加密的逻辑 return user # ... 省略代码 ``` 测试添加数据,先删除历史的数据,在执行添加 ![BLOG_20190530_143705_26](/media/blog/images/2019/05/BLOG_20190530_143705_26.png "博客图集BLOG_20190530_143705_26.png") ![BLOG_20190530_143659_24](/media/blog/images/2019/05/BLOG_20190530_143659_24.png "博客图集BLOG_20190530_143659_24.png") ![BLOG_20190530_143653_93](/media/blog/images/2019/05/BLOG_20190530_143653_93.png "博客图集BLOG_20190530_143653_93.png") 现在序列化不显示密码,只会显示`username`、`mobile`,及密码存储数据库为不可逆密文保存。 此时 user/serializers.py 中序列化类`UserSerializer`内容如下 ```python class UserSerializer(serializers.ModelSerializer): code = serializers.CharField(required=True, min_length=4, max_length=4, help_text='验证码', label='验证码', write_only=True, # 更新或创建实例时可以使用该字段,但序列化时不包含该字段 error_messages={ 'blank': '请输入验证码', 'required': '该字段必填项', 'min_length': '验证码格式不正确', 'max_length': '验证码格式不正确', }) username = serializers.CharField(required=True, allow_blank=False, help_text='用户名', label='用户名', validators=[UniqueValidator(queryset=User.objects.all(), message='用户已存在')]) password = serializers.CharField(required=True, help_text='密码', label='密码', write_only=True, style={'input_type': 'password'}) def validate_code(self, code): # 验证code # self.initial_data 为用户前端传过来的所有值 verify_codes = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by('-add_time') if verify_codes: last_record = verify_codes[0] # 发送验证码如果超过某个时间就提示过期 three_minute_ago = now() - timedelta(hours=0, minutes=3, seconds=0) # 获取三分钟以前的时间 if last_record.add_time < three_minute_ago: # 3ago now # add1 add2 add1就过期 raise serializers.ValidationError('验证码已过期') # 比较传入的验证码 if last_record.code != code: raise serializers.ValidationError('验证码输入错误') # return code # 这没必要return,因为code这个字段只是用来验证的,不是用来保存到数据库中的 else: # 没有查到该手机号对应的验证码 raise serializers.ValidationError('验证码错误') def validate(self, attrs): """ code 这个字段是不需要保存数据库的,不需要改字段 validate这个函数作用于所有的字段之上 :param attrs: 每个字段validate之后返回的一个总的dict :return: """ attrs['mobile'] = attrs['username'] # mobile不需要前端传过来,就直接后台取username中的值填充 del attrs['code'] # 删除不需要的code字段 return attrs def create(self, validated_data): user = super(UserSerializer, self).create(validated_data=validated_data) # user对象是Django中继承的AbstractUser # UserProfile-->AbstractUser-->AbstractBaseUser中有个set_password(self, raw_password)方法 user.set_password(validated_data['password']) # 取出password密码,进行加密后保存 user.save() # ModelSerializer有一个save()方法,save()里面会调用create()函数,这儿重载了create()函数,加入加密的逻辑 return user class Meta: model = User fields = ('username', 'mobile', 'code', 'password') # username是Django自带的字段,与mobile的值保持一致 ``` #### Django信号量实现用户密码加密 在`UserSerializer`中,能否不加入以下逻辑,或者说不重载`create()`方法实现密码加密功能 ```python class UserSerializer(serializers.ModelSerializer): # ...省略代码 def create(self, validated_data): user = super(UserSerializer, self).create(validated_data=validated_data) # user对象是Django中继承的AbstractUser # UserProfile-->AbstractUser-->AbstractBaseUser中有个set_password(self, raw_password)方法 user.set_password(validated_data['password']) # 取出password密码,进行加密后保存 user.save() # ModelSerializer有一个save()方法,save()里面会调用create()函数,这儿重载了create()函数,加入加密的逻辑 return user # ...省略代码 ``` 是否可以写到另一个分离的地方。可以使用Django的信号量。 可以参考Django的信号: https://docs.djangoproject.com/zh-hans/2.2/topics/signals/ Django包含一个“信号调度器”,它允许在框架的其他地方发生操作时通知已解耦的应用程序。简而言之,信号允许某些发送方通知一组接收方某些操作已经发生。当许多代码段可能对相同的事件感兴趣时,它们尤其有用。 Django发送的所有信号的列表。所有内置信号都使用`send()`方法发送。 https://docs.djangoproject.com/zh-hans/2.2/ref/signals/ 在DRF也有处理信号的,参考 https://www.django-rest-framework.org/api-guide/authentication/#by-using-signals ,在示例中,如果希望每个用户都有一个自动生成的令牌,只需捕获用户的`post_save`信号。 在 users 应用下创建 signals.py 文件,用于保存信号函数,参考创建`token`信号的函数,用来在新建用户时加密密码。 首先注释掉`UserSerializer`序列化类中的create()函数 ```python class UserSerializer(serializers.ModelSerializer): # ...省略代码 # def create(self, validated_data): # user = super(UserSerializer, self).create(validated_data=validated_data) # user对象是Django中继承的AbstractUser # # UserProfile-->AbstractUser-->AbstractBaseUser中有个set_password(self, raw_password)方法 # user.set_password(validated_data['password']) # 取出password密码,进行加密后保存 # user.save() # # ModelSerializer有一个save()方法,save()里面会调用create()函数,这儿重载了create()函数,加入加密的逻辑 # return user ``` 改用信号来完成,编辑 signals.py 文件 ```python from django.conf import settings from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth import get_user_model User = get_user_model() @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_user(sender, instance=None, created=False, **kwargs): if created: password = instance.password # instance指的就是创建的用户对象 instance.set_password(password) instance.save() ``` `settings.AUTH_USER_MODEL`可以直接用`User`表示。 `sender`表示接收`User`这个Model传递过来的信号,在传过来后,它需要确认是否是`created`新建数据,如果是新建数据,才进行密码加密。因为如果是update更新的时候也会传递`post_save`信号。使用信号,代码分离性较强。 这些逻辑写完之后还需要加个配置,修改 users/apps.py 重载`UsersConfig`的`ready`方法 ```python from django.apps import AppConfig class UsersConfig(AppConfig): name = 'users' verbose_name = '用户' def ready(self): from users.signals import create_user ``` ![BLOG_20190530_143640_13](/media/blog/images/2019/05/BLOG_20190530_143640_13.png "博客图集BLOG_20190530_143640_13.png") ![BLOG_20190530_143628_39](/media/blog/images/2019/05/BLOG_20190530_143628_39.png "博客图集BLOG_20190530_143628_39.png") ![BLOG_20190530_143623_18](/media/blog/images/2019/05/BLOG_20190530_143623_18.png "博客图集BLOG_20190530_143623_18.png") 恢复运行,可以得到返回的序列化数据 ![BLOG_20190530_143612_49](/media/blog/images/2019/05/BLOG_20190530_143612_49.png "博客图集BLOG_20190530_143612_49.png") 在后台也可以看到已加密的密码 ![BLOG_20190530_143606_89](/media/blog/images/2019/05/BLOG_20190530_143606_89.png "博客图集BLOG_20190530_143606_89.png")
很赞哦! (0)
相关文章
文章交流
- emoji
当前用户
未登录,点击 登录专题目录
- 【Vue+DRF生鲜电商】01.课程结构介绍,开发环境搭建
- 【Vue+DRF生鲜电商】02.设置users、goods、trade、user_operation数据库并导入原始数据
- 【Vue+DRF生鲜电商】03.Restful API基础
- 【Vue+DRF生鲜电商】04.Vue项目结构介绍
- 【Vue+DRF生鲜电商】05.商品列表序列化普通方法
- 【Vue+DRF生鲜电商】06.DRF环境配置,使用Serializer类序列化商品列表
- 【Vue+DRF生鲜电商】07.序列化商品分页功能
- 【Vue+DRF生鲜电商】08.ViewSets & Routers显示商品列表
- 【Vue+DRF生鲜电商】09.使用DRF的filter过滤商品列表
- 【Vue+DRF生鲜电商】10.商品分类层级获取,Vue跨域请求商品分类
- 【Vue+DRF生鲜电商】11.Vue展示左侧分类、面包屑、排序、商品列表、分页
- 【Vue+DRF生鲜电商】12.用户登录之DRF Token认证登录原理和使用方法
- 【Vue+DRF生鲜电商】13.JWT用户认证原理配置,Vue登录接口调试
- 【Vue+DRF生鲜电商】14.用户注册发送短信验证码、登录字段验证
- 【Vue+DRF生鲜电商】15.用户注册使用信号量实现密码加密
- 【Vue+DRF生鲜电商】16.Vue中注册、退出功能交互
- 【Vue+DRF生鲜电商】17.DRF实现商品详情及热卖商品接口,Vue中显示商品详情和热卖
- 【Vue+DRF生鲜电商】18.用户收藏、取消收藏商品接口实现
- 【Vue+DRF生鲜电商】19.用户添加、删除收藏权限处理,根据商品id显示收藏,在Vue中实现收藏功能
- 【Vue+DRF生鲜电商】20.使用DRF自动生成文档的功能
- 【Vue+DRF生鲜电商】21.用户中心个人资料的展示,并在Vue中实现个人资料更新
- 【Vue+DRF生鲜电商】22.个人中心显示用户收藏功能,对收藏进行删除
- 【Vue+DRF生鲜电商】23.个人中心用户留言功能
- 【Vue+DRF生鲜电商】24.用户收货地址功能
- 【Vue+DRF生鲜电商】25.商品添加购物车接口功能,Vue和购物车联调
- 【Vue+DRF生鲜电商】26.使用Pycharm远程代码调试服务器Django代码
- 【Vue+DRF生鲜电商】26.订单接口功能,Vue和订单接口联调
- 【Vue+DRF生鲜电商】27.支付宝公钥,私钥,沙箱环境配置
- 【Vue+DRF生鲜电商】28.支付宝支付接口类解读,支付逻辑编辑
- 【Vue+DRF生鲜电商】29.线上服务支付宝接口和Vue联调,Django代理Vue运行
- 【Vue+DRF生鲜电商】30.首页轮播图、新品展示功能
- 【Vue+DRF生鲜电商】31.首页商品按分类显示推荐功能
- 【Vue+DRF生鲜电商】32.商品操作后计数更改,热搜榜关键字功能实现
- 【Vue+DRF生鲜电商】33.数据缓存、接口访问限速功能
- 【Vue+DRF生鲜电商】34.第三方登录(微博、qq和微信)之微博登录登录测试
- 【Vue+DRF生鲜电商】35.使用social-app-django集成第三方登录