def get(self, request): access_token = request.query_params.get("access_token") if not access_token: return Response({"message": "缺少access_token"}, status=status.HTTP_400_BAD_REQUEST) mobile = User.check_sms_access_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("sms_flag_%s" % mobile) if send_flag: return Response({"message": "发送短信验证码过于频繁"}, status=status.HTTP_429_TOO_MANY_REQUESTS) # 生成验证码并发送 sms_code = '%06d' % random.randint(0, 999999) pipeline = redis_conn.pipeline() # 收集命令 pipeline.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRE, sms_code) pipeline.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 提交执行 pipeline.execute() # 使用Redis的pipeline管道,一次处理多e个命令 # ccp = CCP() # time = str(constants.SMS_CODE_REDIS_EXPIRE / 60) # ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_CODE_TEMPLATE_ID) code = redis_conn.get('sms_%s' % mobile).decode() print("{}手机号验证码:{}".format(mobile, code)) send_sms.delay(mobile, sms_code) return Response({"message": "ok"})
def get(self, request, mobile): # 接收 image_code_request = request.GET.get('image_code') uuid = request.GET.get('image_code_id') # 验证 # 1.图片验证码是否正确 # 1.1读取redis中的图片验证码 redis_cli = get_redis_connection('verify_code') image_code_redis = redis_cli.get(uuid) # 1.2判断是否过期 if image_code_redis is None: return http.JsonResponse({ 'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码已经过期' }) # 1.3对比 # 注意1:在redis读取的数据,都是bytes类型 # 注意2:不区分大小写 if image_code_redis.decode() != image_code_request.upper(): return http.JsonResponse({ 'code': RETCODE.IMAGECODEERR, 'errmsg': '图片验证码错误' }) # 1.4强制图片验证码过期 redis_cli.delete(uuid) # 2.在60秒内只向指定手机号发一次短信 if redis_cli.get('sms_flag_' + mobile): return http.JsonResponse({ 'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁' }) # 处理 # 1.生成6位随机数 sms_code = '%06d' % random.randint(0, 999999) # # 2.保存到redis中 # redis_cli.setex('sms_' + mobile, constants.SMS_CODE_EXPIRES, sms_code) # # 是否在60秒内发送短信的标记 # redis_cli.setex('sms_flag_' + mobile, constants.SMS_CODE_FLAG_EXPIRES, 1) # 优化redis:只与redis服务器交互一次 redis_pl = redis_cli.pipeline() redis_pl.setex('sms_' + mobile, constants.SMS_CODE_EXPIRES, sms_code) redis_pl.setex('sms_flag_' + mobile, constants.SMS_CODE_FLAG_EXPIRES, 1) redis_pl.execute() # 3.发短信 # time.sleep(5) # ccp = CCP() # ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES / 60], 1) # print(sms_code) # 调用任务 send_sms.delay(mobile, [sms_code, constants.SMS_CODE_EXPIRES / 60], 1) # 响应 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': "OK"})
def get(self, request, mobile): strict_redis = get_redis_connection('sms_codes') # type:StrictRedis # 校验短信验证码是否重复发送(1分钟内禁止重复发送) send_flag = strict_redis.get('send_flag_%s' % mobile) if send_flag: raise ValidationError({'message': '频繁获取短信验证码'}) # 生成短信验证码(云通讯) sms_code = '%06d' % random.randint(0, 999999) logger.info('短信验证码:%s %s' % (mobile.sms_code)) # # 2. 发送短信验证码(云通讯) # CCP().send_template_sms(mobile, [sms_code, 5], 1) # sleep(5) # 使用celery来发送短信, 可以解决阻塞问题 send_sms.delay('13600000000', '123456') # 使用管道优化代码 pipeline = strict_redis.pipeline() pipeline.setex('sms_%s' % mobile, 60 * 5, sms_code) pipeline.setex('send_flag_%s' % mobile, 60, 1) result = pipeline.execute() # 管道列表 print(result) # 响应数据 return Response({'message': 'OK'})
def get(self, request, mobile): strict_redis = get_redis_connection('sms_codes') # 60秒内禁止重复发送短信验证码 send_flag = strict_redis.get('send_flag_%s' % mobile) if send_flag: return Response({'message': '发送短信过于频繁'}) # 生成短信验证码 import random sms_code = '%06d' % random.randint(0, 999999) loggers.info('sms_code:%s' % sms_code) # 使用云通讯发送短信验证码 # result = CCP().send_template_sms(mobile,[sms_code,5],1) # print(result) print("验证码:", sms_code) # 保存短信验证码到redis expiry # strict_redis.setex('sms_%s' % mobile,5*60,sms_code) # 有效期5分钟 # strict_redis.setex('send_flag_%s' % mobile,60,1) # 使用selery发送短信验证码 send_sms.delay(mobile, sms_code) # 获取pipeline对象 pipeline = strict_redis.pipeline() pipeline.setex('sms_%s' % mobile, 5 * 60, sms_code) # 有效期5分钟 pipeline.setex('send_flag_%s' % mobile, 60, 1) pipeline.execute() #一次性执行多个命令 return Response({'message': 'ok'})
def get(self, request, mobile): """发送短信""" # 1. 验证手机号是否已经注册过 try: User.objects.get(mobile=mobile) return Response({"message": "对不起,当前手机号已经被注册"}, status=status.HTTP_400_BAD_REQUEST) except User.DoesNotExist: # 如果手机号不存在于数据库,则表示没有注册,不进行任何处理 pass # 2. 验证短信的发送间隔时间[60s] # 2.1 链接redis redis = get_redis_connection("sms_code") # 使用get获取指定键的值,如果获取不到,则返回None interval = redis.get("exp_%s" % mobile) if interval: return Response({"message": "对不起,短信发送间隔太短!"}, status=status.HTTP_403_FORBIDDEN) # 3.1 生成随机的短信验证码 sms_code = "%06d" % random.randint(0, 999999) # 3.2 保存发送的验证码到redis中[手机号码、短信验证码、短信发送间隔、短信有效期] # 3.3 调用sdk发送短信 # 没有使用异步任务框架celery之前的代码 # ccp = CCP() # result = ccp.send_template_sms(mobile, [sms_code, settings.SMS_EXPIRE_TIME//60 ], settings.SMS_TEIMPLATE_ID) # 使用异步任务框架celery之后的代码: from celery_tasks.sms.tasks import send_sms send_sms.delay(mobile, sms_code) # 4. 返回发送短信的结果 # if result == -1: # return Response({"message":"短信发送失败!"},status=status.HTTP_500_INTERNAL_SERVER_ERROR) # else: """ 字符串 setex sms_手机号 300 短信验证码 setex exp_手机号 60 _ """ # 事务操作[pipeline是一个管道对象] pipe = redis.pipeline() pipe.multi() # 开启事务 redis.setex("sms_%s" % mobile, settings.SMS_EXPIRE_TIME, sms_code) redis.setex("exp_%s" % mobile, settings.SMS_INTERVAL_TIME, "_") pipe.excute() # 执行事务 return Response({"message": "短信发送成功!"}, status=status.HTTP_200_OK)
def get(self, request, mobile): # 接受uuid uuid = request.GET.get('image_code_id') image_code = request.GET.get('image_code') # 验证 是否存在六十秒 redis_cli = get_redis_connection('sms_code') if redis_cli.get(mobile + '_flag') is not None: return http.JsonResponse({ 'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁。。' }) if not all([uuid, image_code]): return http.JsonResponse({ 'code': RETCODE.PARAMERR, 'errmsg': '参数不完整' }) # 图形验证码是否正确 redis_cli = get_redis_connection('image_code') image_code_redis = redis_cli.get(uuid) if image_code_redis is None: return http.JsonResponse({ 'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效,点击更换一个' }) # 删除图形验证码 表示不能使用第二次 redis_cli.delete(uuid) if image_code_redis.decode().lower() != image_code.lower(): return http.JsonResponse({ 'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码错误' }) # 生成随机数 sms_code = "%06d" % random.randint(0, 999999) # redis_cli.setex(mobile, constans.SMS_CODE_EXPIRES, sms_code) # # 写发标志防止 重复刷新 # redis_cli.setex(mobile + '_flag', constans.SMS_CODE_FLAG, 1) # 发短信 redis_cli = get_redis_connection('sms_code') redis_pl = redis_cli.pipeline() # 存入验证码 redis_pl.setex(mobile, constans.SMS_CODE_EXPIRES, sms_code) # 存入标识符防止刷新 redis_pl.setex(mobile + '_flag', constans.SMS_CODE_FLAG, 1) # 一次提供两行 减少于redis的交互 redis_pl.execute() # 使用管道技术节省空间 # ccp=CCP() # ccp.send_template_sms(mobile, [sms_code,constans.SMS_CODE_EXPIRES/60],1) # 通过delay调用,可以将任务加到队列中,交给celery去执行 send_sms.delay(mobile, sms_code) print(sms_code) return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})
def get(self, request, mobile): # 接收 uuid = request.GET.get('image_code_id') image_code = request.GET.get('image_code') # 验证 redis_cli = get_redis_connection('sms_code') # 0.是否60秒内 if redis_cli.get(mobile + '_flag') is not None: return http.JsonResponse({'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁,请稍候再发'}) # 1.非空 if not all([uuid, image_code]): return http.JsonResponse({"code": RETCODE.PARAMERR, 'errmsg': '参数不完整'}) # 2.图形验证码是否正确 # 2.1从redis中读取之前保存的图形验证码文本 redis_cli = get_redis_connection('image_code') image_code_redis = redis_cli.get(uuid) # 2.2如果redis中的数据过期则提示 if image_code_redis is None: return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已过期,点击图片换一个'}) # 2.3立即删除redis中图形验证码,表示这个值不能使用第二次 redis_cli.delete(uuid) # 2.3对比图形验证码:不区分大小写 if image_code_redis.decode().lower() != image_code.lower(): return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码错误'}) # 处理 # 1.生成随机6位数 sms_code = '%06d' % random.randint(0, 999999) # # 2.1存入redis # redis_cli.setex(mobile, constants.SMS_CODE_EXPIRES, sms_code) # # 2.2写发送标记 # redis_cli.setex(mobile + '_flag', constants.SMS_CODE_FLAG, 1) # 优化:使用管道 redis_pl = redis_cli.pipeline() redis_pl.setex(mobile, constants.SMS_CODE_EXPIRES, sms_code) redis_pl.setex(mobile + '_flag', constants.SMS_CODE_FLAG, 1) redis_pl.execute() # 3.发短信 # ccp = CCP() # ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES / 60], 1) # print(sms_code) # 通过delay调用,可以将任务加到队列中,交给celery去执行 send_sms.delay(mobile, sms_code) # 响应 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
def get(self, request, mobile): # 获取StrictRedis保存数据 strict_redis = get_redis_connection("sms_codes") #type: StrictRedis # 4. 60秒之内禁止重复发送验证码 sms_flag = strict_redis.get("sms_flag_%s" % mobile) if sms_flag: return Response({"message": "发送短信过于频繁"}, status=400) # 1.生成短信验证码 import random sms_code = "%06d" % random.randint(0, 999999) logger.info('sms_code: %s' % sms_code) # 2.使用云通讯发送短信 # CCP().send_template_sms(mobile, [sms, 5], 1) # sleep(5) # 使用celery发送耗时验证码 send_sms.delay(mobile, sms_code) print(sms_code) # 3.保存短信验证码到redis中 strict_redis.setex("sms_%s" % mobile, 5 * 60, sms_code) strict_redis.setex("sms_flag_%s" % mobile, 60, 1) return Response({"message": "OK"})
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_EXPIRE, sms_code) # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 获取管道 pipeline = redis_conn.pipeline() # 收集命令 pipeline.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRE, sms_code) pipeline.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) # 提交执行 pipeline.execute() # 使用Redis的pipeline管道,一次处理多e个命令 # ccp = CCP() # time = str(constants.SMS_CODE_REDIS_EXPIRE / 60) # ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_CODE_TEMPLATE_ID) code = redis_conn.get('sms_%s' % mobile).decode() print("{}手机号验证码:{}".format(mobile, code)) send_sms.delay(mobile, sms_code) return Response({"message": "ok"})