def get(self,request,mobile): # 校验图片验证码和发送短信的频次 # mobile是被放到了类试图对象属性kwargs中 serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 校验通过 # 生产短信验证码 sms_code = '%06d' % random.randint(0,999999) # 保存验证码及发送记录 redis_conn = get_redis_connection("verify_codes") # redis_conn.setex('sms_{}'.format(mobile),constants.SMS_CODE_REDIS_EXPIRES,sms_code) # redis_conn.setex('send_flag_{}'.format(mobile),constants.SEND_SMS_CODE_INTERVAL,1) # 使用redis的pipeline管道一次执行多个命令 pl = redis_conn.pipeline() pl.setex('sms_{}'.format(mobile),constants.SMS_CODE_REDIS_EXPIRES,sms_code) pl.setex('send_flag_{}'.format(mobile),constants.SEND_SMS_CODE_INTERVAL,1) # 让管道执行命令 pl.execute() # 发送短信 # ccp = CCP() # ccp.send_tempate_sms(mobile,[sms_code,"5"],constants.SMS_CODE_TEMP_ID) # 使用celery发布异步任务 send_sms_code.delay(mobile,sms_code) # 返回 return Response({'message':'OK'})
def get(self, request, mobile): """ 校验图片验证码和发送短信的频次 mobile是被放到了类视图对象属性kwaargs中 """ serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 校验通过 # 生成短信验证码 sms_code = "%06d" % random.randint(0, 999999) print(sms_code) # 保存短信验证码与发送记录 redis_conn = get_redis_connection('verify_codes') # 保存验证码及发送记录 # 使用redis的pipeline管道一次执行多条命令 pl = redis_conn.pipeline() pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 让管道执行命令 pl.execute() # 发送短信验证码 # ccp = CCP() # time = str(constants.SMS_CODE_REDIS_EXPIRES // 60) # ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_CODE_TEMP_ID) # 使用celery发布异步任务 send_sms_code.delay(mobile, sms_code) # 返回 return Response({"message": "OK"})
def get(self, request, mobile): # 0.创建redis连接对象 redis_conn = get_redis_connection('verify_codes') # 1.获取此手机号是否有发送过的标记 flag = redis_conn.get('send_flag_%s' % mobile) # 2.如果已发送就提前响应,不执行后续代码 if flag: # 如果if成立说明此手机号60秒内发过短信 return Response({'message': '频繁发送短信'}, status=status.HTTP_400_BAD_REQUEST) # 3.生成短信验证码 sms_code = '%06d' % randint(0, 999999) logger.info(sms_code) # 创建redis管道对象 pl = redis_conn.pipeline() # 4.把验证码存储到redis中 # redis_conn.setex(key, 过期时间, value) # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 4.1 存储此手机号已发送短信标记 # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 执行管道 pl.execute() # 5.利用容联云通讯发短信 # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1) # 触发异步任务(让发短信不要阻塞主线程) # send_sms_code(mobile, sms_code) send_sms_code.delay(mobile, sms_code) # 6.响应 return Response({'message': 'ok'})
def get(self, request, mobile): # 校验图片验证码和发送短信的频次 # mobile是被放到了类视图对象属性kwargs中 # mobile在url的正则中验证 # 所以反序列化的data中只传查询参数 query_params serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 校验通过 # 生成短信验证码 sms_code = '%06d' % random.randint(0, 999999) # 保存验证码及发送记录 redis_conn = get_redis_connection('verify_codes') # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 使用redis的pipeline管道一次执行多个命令 pl = redis_conn.pipeline() pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 60S来控制已经发送短信 # 让管道执行命令 pl.execute() # 发送短信 # ccp = CCP() # time = str(constants.SMS_CODE_REDIS_EXPIRES / 60) # ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_CODE_TEMP_ID) # 使用celery发布异步任务 send_sms_code.delay(mobile, sms_code) print(sms_code) # 返回 return Response({'message': 'OK'})
def post(self, request): # 校验手机号码 mobile = request.data.get("mobile") mobile = re.match("1[3-9][0-9]{9}$", mobile) if not mobile: return Response(data={"code": "400", "messages": "手机号码格式错误"}) mobile = mobile.group() # 查询手机号是否被注册 user = User.objects.filter(mobile=mobile) if user: return Response(data={"messages": "手机号码已经被注册"}) # 校验是否频繁发送 redis_conn = get_redis_connection( alias="verify_codes") # type:StrictRedis send_flag = redis_conn.get("%s_flag" % mobile) if send_flag: # 短信验证码存在 return Response(data={"messages": "请求频繁"}) sms_code = redis_conn.get("%s_code" % mobile) if not sms_code: # 生成新的短信验证码 sms_code = "%06d" % random.randint(0, 999999) # 存储验证码到redis数据库 redis_conn.set("%s_code" % mobile, sms_code, ex=60 * 5) else: sms_code = sms_code.decode("utf-8") redis_conn.set("%s_flag" % mobile, 1, ex=60) # 一分钟后自动清除 # 7.执行异步任务发送验证码 send_sms_code.delay(mobile, sms_code) print(sms_code) return Response(data={"messages": "短信验证码发送成功"})
def get(self, request, mobile): # 1. 创建redis连接对象 redis_conn = get_redis_connection('verify_codes') # 2. 从redits中获取发送标记 # 60秒内不允许重发发送短信 send_flag = redis_conn.get('send_flag_%s' % mobile) # 3.如果获取到类标记,说明手机号频繁发送短信 if send_flag: return Response({"message": "发送短信过于频繁"}, status=status.HTTP_400_BAD_REQUEST) # 4. 生成验证码 sms_code = '%06d' % random.randint(0, 999999) logger.info(sms_code) # 创建redis管道 把多次redis操作装入管道中,将来一次性去执行,减少redis连接操作 pl = redis_conn.pipeline() # 5. 把验证码存储到redis数据库 pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 6. 把验证码存储到redis数据库 pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 执行管道 pl.execute() # 7. 利用容联云通讯发送短信验证码 # CCP().send_template_sms(self, 手机号, [验证码,5], 1): # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1) # celery异步发送短信 send_sms_code.delay(mobile, sms_code) # 8. 响应 return Response({'message': 'ok'})
def get(self, request: Request, mobile): # 校验图片验证码和发送短信的频次 # mobile是被放到了类视图对象中,只要不是查询字符串和请求体,都是存放在view的kwargs属性中 serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 校验通过,生成短信验证码 sms_code = '%06d' % random.randint(0, 999999) # 保存验证码以及发送记录 redis_conn = get_redis_connection('verify_codes') # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 使用redis的pipeline管道一次执行多个redis命令 pl = redis_conn.pipeline() pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 让管道执行命令 pl.execute() # 发送短信(交给celery异步执行耗时任务) # ccp = CCP() # ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SMS_CODE_TEMP_ID) # 使用celery发布异步任务 send_sms_code.delay(mobile, sms_code) return Response({'message': 'OK'})
def get(self, request, mobile): # 1.获取前端传递的手机号,路径中进行正则匹配 # 判断前端发送请求的时间间隔 60s # 建立链接redis的对象 conn = get_redis_connection('sms_code') flag = conn.get('sms_code_flag_%s' % mobile) if flag: return Response({'error': '请求过于频繁'}, status=400) # 2.生成短信验证码 sms_code = '%06d' % randint(0, 999999) # 3.保存验证码到缓存中 # 建立链接redis对象 conn = get_redis_connection('sms_code') # string类型写入 # setex三个参数,第一个参数是key值,第二个是有效期,第三个是value值 # 常规用法 # conn.setex('sms_code_%s'%mobile, 300, sms_code) # conn.setex('sms_code_flag_%s' % mobile, 60, 1) # 管道用法 pl = conn.pipeline() pl.setex('sms_code_%s' % mobile, 300, sms_code) pl.setex('sms_code_flag_%s' % mobile, 60, 1) # 连接redis缓存,传入写入指令 pl.execute() # 4.发送短信 # ccp = CCP() # ccp.send_template_sms(mobile, [sms_code, '5'], 1) # 使用线程发送短信 # t = Thread(target='send_sms_code', kwargs={'mobile': mobile, 'sms_code': sms_code}) # t.start() # t.join() # 使用celery发送短信 send_sms_code.delay(mobile, sms_code) # 5.结果返回 return Response({'message': 'ok'})
def get(self, request, mobile): """ 限制60秒内只能向个一个手机号码发送一次短信验证码 """ # 获取Redis的连接: 从配置中的cache处,根据名称获取连接 redis_cli = get_redis_connection('sms_code') # 1.判断60秒内是不是向指定手机号码发过短信,如果发过,则抛异常 if redis_cli.get('sms_flag_' + mobile): raise serializers.ValidationError('您发送短信太过频繁') # 2.如果未发短信,则随机生成6位随机数 code = random.randint(100000, 999999) code = 123456 # 2.1 保存到redis:验证码,发送的标记 优化(使用pipeline管道) redis_pipeline = redis_cli.pipeline() redis_pipeline.setex('sms_code_' + mobile, constants.SMS_CODE_EXPIRES, code) redis_pipeline.setex('sms_flag_' + mobile, constants.SMS_FLAG_EXPIRES, 1) redis_pipeline.execute() # 3.发送短信:云通讯 # CCP.sendTemplateSMS(mobile, code, constants.SMS_CODE_EXPIRES/60, 1) # 调用celery任务,执行耗时代码 send_sms_code.delay(mobile, code, constants.SMS_CODE_EXPIRES / 60, 1) # 4.响应 return Response({'message': 'ok'})
def get(self,request,mobile): # 获取redis的链接 redis_cli = get_redis_connection('sms_code') #1.判断60s内是否向手机发过短信 # 如发过,抛出异常 if redis_cli.get('sms_flag_'+mobile): raise serializers.ValidationError('此手机在60s秒内已发送过验证码') #2.如果未发送短信 #2.1 获取随机的6位数 code = random.randint(100000,999999) #2.2 保存到redis中 验证码 发送的标记 # redis_cli.setex('sms_code_'+mobile,300,code) # redis_cli.setex('sms_flag_' + mobile, 60, 1) # 优化:pipeline # 减少与redis数据库交互的次数,现在只交互一次,之前交互两次 redis_pipeline=redis_cli.pipeline() redis_pipeline.setex('sms_code_'+mobile,constans.SMS_CODE_EXPIRES,code) redis_pipeline.setex('sms_flag_' + mobile, constans.SMS_FLAG_EXPIRES, 1) redis_pipeline.execute() #2.3 发短信 云通信 # CCP.sendTemplateSMS(mobile,code,constans.SMS_CODE_EXPIRES/constans.SMS_FLAG_EXPIRES,1) # print(code) # 调用celery任务,执行耗时代码 send_sms_code.delay(mobile,code,constans.SMS_CODE_EXPIRES/60,1) print(code) #3.响应 return Response({'message':'OK'})
def get(self,request,mobile): """ GET /sms_codes/(?P<mobile>1[3-9]\d{9})/ :param request: :param mobile: :return: """ # 0.创建redis连接对象 redis_conn = get_redis_connection('verify_codes') # 1.获取此手机号是否有发送过的标记 flag = redis_conn.get('send_flag_%s' % mobile) # 2.如果已发送就提前响应,不执行后续代码 if flag: # 如果if成立说明此手机号60秒内发过短信 return Response({'message': '频繁发送短信'}, status=status.HTTP_400_BAD_REQUEST) # 3生成六位随机验证码 smc_code='%06d' % randint(0,999999) logger.info(smc_code) # 创建redis的管道命令 pl = redis_conn.pipeline() # 4把短信验证码缓存到redis setex(key 过期时间, value) pl.setex('sms_%s' % mobile,constants.SMS_CODE_REDIS_EXPIRES,smc_code) # 4.1 存储此手机号已发送短信标记 pl.setex('send_flag_%s' % mobile, constants.SMS_CODE_REDIS_SIANS, 1) # 执行管道 pl.execute() # 5使用容联云通讯去发送短信 send_template_sms(self, to, datas, temp_id) # CCP().send_template_sms( mobile,[smc_code,constants.SMS_CODE_REDIS_EXPIRES // 60],1) # 触发异步任务(让发短信不要阻塞主线程) send_sms_code.delay(mobile, smc_code) # 6响应结果 return Response({'message':'OK'})
def get(self, request, mobile): image_code = request.GET.get('image_code') image_code_id = request.GET.get('image_code_id') if not all([image_code, image_code_id]): return http.JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必传参数'}) redis_conn = get_redis_connection('verify_code') redis_str = redis_conn.get('img_%s' % image_code_id) redis_flag = redis_conn.get(mobile) if redis_str is None: return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码超时'}) redis_str = redis_str.decode().lower() try: redis_conn.delete('img_%s' % image_code_id) except Exception as e: logger.error(e) if redis_str != image_code.lower(): return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '验证码错误'}) if redis_flag != None: return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '访问过于频繁'}) rand_int = '%06d' % random.randint(0, 999999) logger.info(rand_int) redis_conn = get_redis_connection('verify_code').pipeline() redis_conn.setex('%s_%s' % (rand_int, mobile), 300, rand_int) redis_conn.setex('%s' % mobile, 60, 1) redis_conn.execute() send_sms_code.delay(mobile,rand_int) return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
def get(self, request, mobile): # 链接到redis数据库 redis_conn = get_redis_connection('verify_code') # 判断已为当前手机号发送验证码 send_flag = redis_conn.get('send_flag_%s' % mobile) # 如果短信发送标志存在则不产生新验证码 if send_flag: return Response({'message': '频繁发送短信'}, status=status.HTTP_400_BAD_REQUEST) # 生成六位数字验证码 sms_code = '%06d' % random.randint(0, 999999) logger.info(sms_code) # 创建数据库管道 pl = redis_conn.pipeline() # 把当前手机号与短信验证码保存到redis数据库 pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 将当前手机号标记为:已发短信验证码 pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) pl.execute() # 使用容联云通讯发送短信验证码 # CCP().send_template_sms(mobile, [sms_code, constants.YUNTONGXUN_EXPIRES], constants.YUNTONGXUN_TEMPLATE) # 通过异步任务发送短信验证码 send_sms_code.delay(mobile, sms_code) # 返回数据 return Response({'message': '0k'})
def get(self, request, mobile): serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 校验通过,生成短信验证码 sms_code = '%06d' % random.randint(0, 999999) # 保存验证码及发送记录 redis_conn = get_redis_connection('verify_codes') # redis_conn.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # redis_conn.setex("send_flag_%s" % mobile, constants.SMS_SEND_INTERVAL, 1) # 使用redis管道代替之前的直接执行命令,可以一次执行多条命令 pl = redis_conn.pipeline() pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex("send_flag_%s" % mobile, constants.SMS_SEND_INTERVAL, 1) # 让管道执行命令 pl.execute() # 发送短信 # ccp = CCP() # sms_time = str(constants.SMS_CODE_REDIS_EXPIRES / 60) # ccp.send_template_sms(mobile, [sms_code, sms_time], constants.SMS_CODE_TEMPLATE_ID) # 使用celery异步实现 send_sms_code.delay(mobile, sms_code) return Response({'message': 'ok'})
def get(self, request, mobile): image_code = request.GET.get('image_code') image_code_id = request.GET.get('image_code_id') if not all([image_code, image_code_id]): return HttpResponseBadRequest('参数不全') from django_redis import get_redis_connection redis_conn = get_redis_connection('code') redis_text = redis_conn.get('img_%s' % image_code_id) if redis_text is None: return HttpResponseBadRequest('图片验证码已过期') if redis_text.decode().lower() != image_code.lower(): return HttpResponseBadRequest('图片验证码不一致') from random import randint sms_code = '%06d' % randint(0, 999999) redis_conn.setex('sms_%s' % mobile, 300, sms_code) # CCP().send_template_sms(mobile,[sms_code,5],1) from celery_tasks.sms.tasks import send_sms_code send_sms_code.delay(mobile, sms_code) return JsonResponse({'msg': 'ok', 'code': '0'})
def get(self, request, mobile): # 0.从redis获取发送标记 redis_conn = get_redis_connection('verify_codes') # 如果获取不到,会返回None send_flag = redis_conn.get('send_flag_%s' % mobile) if send_flag: return Response({'message': '手机号频繁发送短信'}, status=status.HTTP_400_BAD_REQUEST) # 1.生成随机6位数字,不够补0 sms_code = '%06d' % randint(0, 999999) # 2.创建redis管道,减少redis连接操作 pl = redis_conn.pipeline() # 2.1 存储验证码到redis,300秒过期 pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 2.2 存储一个标记,,标识此手机号已发送过短信,有效期60s pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 2.3 执行管道 pl.execute() # 3.调用第三方sdk发送短信 # CCP().send_template_sms(self, 手机号, [验证码, 过期时间], 模板id) # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1) # //表示整除 send_sms_code.delay(mobile, sms_code) # 添加异步任务 logger.info('添加异步任务,发送验证码:{}'.format(sms_code)) # 4.响应 return Response({'messsage': 'ok'})
def get(self, request): access_token = request.GET.get('access_token') user_dict = s.loads(access_token) if user_dict is None: return JsonResponse({}, status=400) mobile = user_dict['mobile'] try: User.objects.get(mobile=mobile) except: return JsonResponse({}, status=400) redis_conn = get_redis_connection('code') if redis_conn.get('sms_%s' % mobile) is not None: return JsonResponse({ 'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁' }) from random import randint sms_code = '%06d' % randint(0, 999999) redis_conn.setex('sms_%s' % mobile, 300, sms_code) from celery_tasks.sms.tasks import send_sms_code send_sms_code.delay(mobile, sms_code) return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
def get(self,request,mobile): # 1.接收前端数据 params = request.query_params # 2. 校验数据 # text = params.get('text') # image_code_id = params.get('dd') # # if not all([text,image_code_id]): # pass # 校验 serializer = RegisterSmscodeSerializer(data=params) # 调用 is_valid 才会校验 serializer.is_valid(raise_exception=True) # 3. 先生成短信 from random import randint sms_code = "%06d"%randint(0,999999) # 4. 保存短信,发送短信 redis_conn = get_redis_connection('code') redis_conn.setex('sms_%s'%mobile,300,sms_code) # CCP().send_template_sms(mobile,[sms_code,5],1) from celery_tasks.sms.tasks import send_sms_code # delay 的参数和send_sms_code 任务的参数是对应的 send_sms_code.delay(mobile,sms_code) # 5. 返回响应 return Response({'msg':'OK'})
def get(self, request, mobile): # 1. 在序列化器中 检查图片验证码 serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 2. 生成短信验证码 sms_code = "%06d" % random.randint(0, 999999) # 3. 保存短信验证码与发送记录 redis_conn = get_redis_connection('verify_codes') # 当项目中连续出现多条操作redis的语句时,可以使用pipeline管道命令,把多条操作 # 组合到一次发送给redis,可以有效提高执行效率 # 通过pipeline方法,获取管道对象,管道对象继承于redis连接对象 # 所以redis中本身支持方法属性,pipeline对象也可以操作 pl = redis_conn.pipeline() pl.multi() pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 发送短信的标志,维护60秒 pl.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) pl.execute() # 把上面组装的操作一并执行 # 4. 发送短信 # ccp = CCP() # time = str(constants.SMS_CODE_REDIS_EXPIRES/60) # ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_TEMP_ID) # 调用celery异步发送短信,异步任务函数中的参数, 必须一一按照顺序填写delay中 send_sms_code.delay(mobile, sms_code) # 5. 返回响应 return Response({"message": "OK"}, status.HTTP_200_OK)
def get(self, request, mobile): #与redis建立链接(指定那个数据库) redis_cli = get_redis_connection('sms_code') ## 1.判断60秒内是不向指定手机号发过短信,如果发过,则抛异常,只需要判断标记存在么 if redis_cli.get('sms_flag' + mobile): raise serializers.ValidationError('向此手机号发短信太频繁了') # 2.如果未发短信,则 # 2.1随机生成6位数 code = random.randint(100000, 999999) print(code) # 2.2保存到redis:验证码,发送的标记 # redis_cli.setex('sms_code_'+mobile,300,code) # redis_cli.setex('sms_flag_'+mobile,60,1) # 优化:pipeline管道 radis_pipeline = redis_cli.pipeline() radis_pipeline.setex('sms_code' + mobile, constants.SMS_CODE_EXPIRES, code) radis_pipeline.setex('sms_flag' + mobile, constants.SMS_FLAG_EXPIRES, 1) radis_pipeline.execute() # 2.3发短信:云通讯 # CCP.sendTemplateSMS(mobile,code,constants.SMS_CODE_EXPIRES/60,1) # print(code) # 调用celery任务,执行耗时代码 send_sms_code.delay(mobile, code, constants.SMS_CODE_EXPIRES / 60, 1) return Response({'message': 'OK'})
def get(self, request: Request): # 获取并校验access_token access_token = request.query_params.get('access_token') if not access_token: return Response({'message': '缺少access_token'}, status=status.HTTP_400_BAD_REQUEST) # 从access_token中获取手机号 mobile = User.check_send_sms_code_token(access_token) if not mobile: return Response({'message': '无效的access_token'}, status=status.HTTP_400_BAD_REQUEST) # 判断手机号发送频次 redis_conn = get_redis_connection('verify_codes') send_flag = redis_conn.get('send_flag_%s' % mobile) if send_flag: return Response({'message': '发送短信次数过于频繁'}, status=status.HTTP_429_TOO_MANY_REQUESTS) # 生成短信验证码 sms_code = '%06d' % random.randint(0, 999999) # 保存并发送短信验证码 pl = redis_conn.pipeline() pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) pl.execute() send_sms_code.delay(mobile, sms_code) return Response({'message': 'OK'})
def get(self, request, mobile): # 判断图片验证码,短信验证码是否在60s内 serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) # 2、校验参数 # 生成短信验证码 sms_code = '%06d' % random.randint(0, 999999) logger.debug(sms_code) # 存储短信到redis数据库 # 生成redis管道,将多个redis指令集成到一起执行,减少访问redis数据库次数 redis_conn = get_redis_connection('verify_codes') pl = redis_conn.pipeline() pl.setex('sms_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 记录发送短信的标记 pl.setex('send_flag_' + mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 开启执行 pl.execute() # 3、业务处理 # 发送短信 # ccp = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES//60], constants.SMS_CODE_TEMP_ID) # 执行异步任务:delay将延迟异步任务发送到redis send_sms_code.delay(mobile, sms_code) # 4、返回结果 return Response({'message': 'OK'})
def get(self, request): access_token = request.GET.get('access_token') try: user_id = pickle.loads(base64.b64decode(access_token.encode())) user = User.objects.get(id=user_id) mobile = user.mobile except: return http.HttpResponseForbidden('无效的access_token') sms_code = '%06d' % randint(0, 999999) logger.info(sms_code) redis_conn = get_redis_connection('verify_code') # redis管道技术 pl = redis_conn.pipeline() # 将短信验证码存储到redis,以备后期注册时校验 # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 向redis多存储一个此手机号已发送过短信的标记,此标记有效期60秒 # redis_conn.setex('send_flag_%s' % mobile, 60, 1) pl.setex('send_flag_%s' % mobile, 60, 1) # 执行管道 pl.execute() # 给当前手机号发短信 # CCP().send_template_sms(要收短信的手机号, [短信验证码, 短信中提示的过期时间单位分钟], 短信模板id) # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1) send_sms_code.delay(mobile, sms_code) # 生产任务 # 响应 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信验证码成功'})
def get(self, request, mobile, celery_tasks=None): # 2. 对图片验证码和uuid进行校验, 手机号也要校验 #需要对数据进行验证(反序列化) #/(?P<mobile>1[3-9]\d{9})/?text=xxxx&image_code_id=xxxx #获取get中的查询字符串的时候需要使用request中的query_params data = request.query_params #创建序列化器械 serializer = RegisterSmscodeSerializer(data=data) serializer.is_valid() #3.需要对手机号发送记录进行判断(60秒之内是否有发送过) redis_conn = get_redis_connection('code') #获取发送的状态 if redis_conn.get('sms_flag_%s'% mobile): return Response(status=status.HTTP_429_TOO_MANY_REQUESTS) #4.生成短信 from random import randint sms_code = '%06d' % randint(0,999999) print('手机验证码为: %s' % sms_code) #5.redis记录短信内容后面注册的时候需要验证 60秒以后过期,用的默认的1号模板 key time value\ # 记录为string redis_conn.setex('sms_%s'%mobile,5*60,sms_code) # 记录发送状态 redis_conn.setex('sms_flag_%s' % mobile, 60, 1) # 6.发送短信 # ccp = CCP() # mobile:向谁发 []:发什么, 60:过期时间, 1:模板 , # ccp.send_template_sms(mobile, [sms_code], 60, 1) from celery_tasks.sms.tasks import send_sms_code # 注意: 异步任务必须使用 delay调用 # delay的参数是 和 任务的参数是一致的 # send_sms_code(mobile,sms_code) --错误代码 不能这样发送 send_sms_code.delay(mobile, sms_code) return Response({'message': 'ok'})
def get(self,request,mobile): #验证码内容的校验(序列化器) serializer = self.get_serializer(data=request.query_params) serializer.is_valid(raise_exception=True) #判断用户是否已经有发送记录 ,防止用户频繁操作 redis_conn = get_redis_connection('code') if redis_conn.get('sms_flag_%s' % mobile): return Response(status=status.HTTP_429_TOO_MANY_REQUESTS) #生成短信验证码 sms_code = '%06d' % randint(0, 999999) #记录发送状态 # redis_conn.setex('sms_%s'%mobile,constants.SMS_CODE_EXIPRE_TIME,sms_code) #1 表示已经发送 # redis_conn.setex('sms_flag_%s'%mobile,60,1) # 创建管道 将一行代码就执行一次redis操作 变成将管道中 的操作一起发送给redis-server 提高效率 pl = redis_conn.pipeline() # 将我们的指令放到管道中 等待统一执行 pl.setex('sms_%s' % mobile, constants.SMS_CODE_EXIPRE_TIME, sms_code) pl.setex('sms_flag_%s' % mobile, 60, 1) # 执行 pl.execute() #发 送 # ccp = CCP() # ccp.send_template_sms(mobile,(sms_code,5),1) from celery_tasks.sms.tasks import send_sms_code send_sms_code.delay(mobile,sms_code) #由于我们的短信下发是同步操作的,同步操作有可能会出现等待的情况,造成响应不能及时返回 #我们就直接采用celery 进行短信下发 return Response({'message':'ok'})
def get(self, request, mobile): # 1.后端接收数据 query_params = request.query_params # 2.校验数据 (数据格式,数据的内容[图片验证码是否正确]) # text = query_params.get('text') # image_code_id=query_params.get('image_code_id') serializer = RegisterSmsCodeSerializer(data=query_params) serializer.is_valid(raise_exception=True) # 3.生成一个短信码 import random sms_code = '%06d' % random.randint(0, 999999) # 4.发送短信 # CCP().send_template_sms(mobile,[sms_code,5],1) from celery_tasks.sms.tasks import send_sms_code # send_sms_code(mobile,sms_code) 错误的 # delay 的参数 同前边函数的参数 send_sms_code.delay(mobile, sms_code) # 5.保存短信 redis_conn = get_redis_connection('code') # redis_conn.setex(key,expire,value) redis_conn.setex('sms_%s' % mobile, 5 * 60, sms_code) # 6.返回相应 return Response({'msg': 'ok'})
def get(self, request, mobile): ''' 限制60秒内只向一个手机号发送一次短信验证码 ''' # 获取Redis的连接:从配置中的cache处,根据名称获取连接 redis_cli = get_redis_connection('sms_code') # 1.判断60秒内是不向指定手机号发过短信,如果发过,则抛异常 if redis_cli.get("sms_flag_" + mobile): raise serializers.ValidationError('向此手机号发短信太频繁了') # 2.如果未发短信,则 #2.1随机生成六位数 code = random.randint(100000, 999999) # 2.2保存到redis:验证码,发送的标记 # redis_cli.setex('sms_code_'+mobile,300,code) # redis_cli.setex('sms_flag_'+mobile,60,1) # 优化:pipeline管道 redis_pipeline = redis_cli.pipeline() redis_pipeline.setex('sms_code_' + mobile, constans.SMS_CODE_EXPIRES, code) redis_pipeline.setex('sms_flag_' + mobile, constans.SMS_FLAG_EXPIRES, 1) redis_pipeline.execute() # 2.3发短信:云通讯 CCP.sendTemplateSMS(mobile, code, constans.SMS_CODE_EXPIRES / 60, 1) print(code) # 调用celery任务,执行耗时代码 send_sms_code.delay(mobile, code, constans.SMS_CODE_EXPIRES / 60, 1) # 3.响应 return Response({'message': 'OK'})
def get(self, request): # 解析token,获取mobile access_token = request.GET.get('access_token') # 创建token对象 token = TOKEN(settings.SECRET_KEY, 300) mobile = token.loads(access_token)['mobile'] # 生成短信验证码 sms_code = '%06d' % randint(0, 999999) logger.info(sms_code) # 创建redis管道对象来用于保存数据,能提高代码运行效率 redis_conn = get_redis_connection('verify_code') pl = redis_conn.pipeline() # 保存短信验证码 pl.setex('sms_%s' % mobile, 60 * 3, sms_code) # 手机号发过短信后在redis中存储一个标记 # redis_conn.setex('send_flag_%s' % mobile, 60, 1) pl.setex('send_flag_%s' % mobile, 60, 1) # 执行管道 pl.execute() # 发送短信验证码 (后面参数信息为 手机号,[验证码, 有效时间单位分钟], 短信模板ID) # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRE // 60], constants.SMS_TEMPLATE_ID) # 将需要执行的任务列表存储在broker send_sms_code.delay(mobile, sms_code) return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '短信发送成功'})
def sms_codes(request): """ 发送短信验证码 :param request: :return: """ mobile = request.GET.get('mobile') redis_conn = get_redis_connection('verify_codes') send_flag = redis_conn.get('send_flag_%s' % mobile) if send_flag: return JsonResponse(data={"error": "发送短信过于频繁", "status": 400}) if not mobile: return JsonResponse(data={"error": "缺少必传参数", "status": 400}) # 判断手机号是否合法 if not re.match(r'^1[3-9]\d{9}$', mobile): return JsonResponse(data={"error": "请输入正确的手机号码", "status": 400}) # ⽣成短信验证码:⽣成6位数验证码 sms_code = '%06d' % random.randint(0, 999999) # CCP().send_template_sms(mobile,[sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID) # celery异步发送短信 send_sms_code.delay(mobile, sms_code) pl = redis_conn.pipeline() # 保存短信验证码 pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 执行 pl.execute() return JsonResponse(data={"message": "发送成功", "status": 200})
def get(self, request, mobile): #创建redis连接对象 redis_conn = get_redis_connection('verify_codes') # 指定数据库名称连接到数据库 # 从redis中获取标记 send_flag = redis_conn.get('send_flag_%s' % mobile) # 取不到也不会报错 是none if send_flag: # 如果取到了标记说明此手机号频繁发送 return Response({'message': '手机频繁发送短信'}, status=status.HTTP_400_BAD_REQUEST) # 生成验证码 sms_code = '%06d' % randint(0, 999999) logger.info(sms_code) # 创建redis管道(把多次redis操作放入管道中将一次性去执行,减少redis连接操作) pl = redis_conn.pipeline() #.把验证码存储到redis数据库 # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 键,存储时间秒,值 pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) # 键,存储时间秒,值 # 存储一个标记表示此手机号已经发送过短信 标记有效期为60s # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 键,存储时间秒,值 pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 键,存储时间秒,值 # 执行管道 pl.execute() # import time # time.sleep(5) #现在是单线程吗 就已经是多任务了吧 服务器自己解决的runserver或者你部署nginx等 #利用容联云通讯发送短信验证码 # CCP().send_template_sms(to, datas, temp_id) to是手机号 datas是列表[验证码,5] 5是分钟表示过期时间 还有短信内容的模板 # CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], 1) # 触发异步任务,将异步任务添加到celery任务队列 send_sms_code(mobile, sms_code) # 这么做是错的 调用普通函数而已 send_sms_code.delay(mobile, sms_code) # 触发异步任务 #响应 return Response({'message': 'ok'})