飞行的猪哼哼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一:准备工作:
1:将yuntongxun包,放在verifications/libs下面。
2:修改云通讯下的ccp_sms.py文件

_accountSid = '8a216da873cec13201744db8f'

# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = 'e6128f3209c843cabe6576'

# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = '8a216da873cec13201744db'

二 :写视图函数:

class SMSCodeView(View):
    # 1:提取参数,用户输入的图片验证码,图片的uuid。
    
    # 2:校验参数
    # 存在性校验
    # 格式校验
    # 匹配校验---用户输入的图片验证码和redis存在的验证码是否相同。
    
    # 3:数据处理---利用云通讯给用户发送验证码
    
    # 生成随机6位数的验证码
    
    # 将验证码写入数据库
    
    # 利用云通讯发送验证码
    
    
    # 4:构建响应
class SMSCodeView(View):

    def get(self, request, mobile):
        # 1、提取参数
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')

        # 2、校验参数
        # 2.1、参数必要性校验
        if not all([image_code, uuid]):
            return JsonResponse({
                'code': 400,
                'errmsg': '参数缺失'
            }, status=400)

        # 2.2、校验image_code
        if not re.match(r'^[a-zA-Z0-9]{4}$', image_code):
            return JsonResponse({
                'code': 400,
                'errmsg': '图形验证码格式有误!'
            }, status=400)

        # 2.3、校验图片验证码的uuid
        if not re.match(r'^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$', uuid):
            return JsonResponse({
                'code': 400,
                'errmsg': 'uuid不符合格式'
            }, status=400)

解释: image_code = request.GET.get(‘image_code’)
uuid = request.GET.get(‘image_code_id’)
提取查询字符串参数,一个是用户输入的验证码,一个是图片的UUID。
2.1表示UUID和用户输入的验证码是必传项。
2.3表示UUID符合UUID的格式

 # 2.4、校验用户输入的图形验证码和redis中记录的是否一致
        # 2.4.1、根据uuid提取redis中的图形验证码
        conn = get_redis_connection('verify_code')

        # 过期:None;
        # 存在:b'ABCD' ---> 'ABCD'
        image_code_from_redis = conn.get('img_%s'%uuid)
        # 图片验证码:读一次,删一次,保证该图片验证码只会被使用"一次"!
        conn.delete('img_%s'%uuid)
        if not image_code_from_redis:
            # 没有读取到redis中的图形验证码 —— 可能过期了
            return JsonResponse({
                'code': 400,
                'errmsg': '图形验证码过期!'
            }, status=403)

        # 读取到了redis的验证码是字符串的字节形式,需要转化成字符串
        image_code_from_redis = image_code_from_redis.decode()

        # 2.4.2、和用户手写的比对
        #  'ABCE' != 'ABCD'
        if image_code.lower() != image_code_from_redis.lower(): # 全部转为小写比较,目的是忽略大小写
            return JsonResponse({
                'code': 400,
                'errmsg': '验证码输入有误'
            }, status=400)


 # 3、数据处理 —— 发送手机短信
        # 3.0、判断redis的短信标志存不存在 —— 存在说明60秒之内用户发送过短信
        send_flag = conn.get('send_flag_%s' % mobile)
        if send_flag:
            return JsonResponse({'code': 400, 'errmsg': '请勿重复发送'}, status=403)

        # 3.1、生成6位短信验证码
        sms_code = "%06d" % random.randint(0, 999999)
        print("短信验证码: ", sms_code)

        # 3.2、短信验证码存入redis缓存
        # 3.2.1、通过redis链接对象获取一个管道
        pl = conn.pipeline()

        # 短信验证码存入redis中,便于用户注册的时候读取比对
        # 以手机号码,作为存入短信验证码的redis中key
        # 通过pl管道对象,调用的函数(执行指令),此处并没有真正的执行,而是暂存
        pl.setex(
            'sms_%s' % mobile,
            300,
            sms_code
        )
        # conn.setex(
        #     'sms_%s' % mobile,
        #     300,
        #     sms_code
        # )
        # 3.3、存入一个标志 —— 表示用户在60秒内发送了短信
        pl.setex(
            'send_flag_%s' % mobile,
            60,
            '1'
        )
        # conn.setex(
        #     'send_flag_%s' % mobile,
        #     60,
        #     '1'
        # )

        # 批量执行管道中暂存的指令
        pl.execute()

        # 3.4、调用容联云接口发送短信
        # 发送短信验证码
        CCP().send_template_sms(
            mobile,
            [sms_code, 5],
            1
        )


        # 4、构建响应
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok'
        })

3:路由映射:

    path('sms_codes/<mobile:mobile>/', views.SMSCodeView.as_view())

三:出现的问题:
1:删除图形验证码:
问什么要删除?图形验证码写错了,请求了,这个验证码就不能再用了。如果不设置只能用一次那么,爬虫就会一直尝试。不安全。
怎么做?读一次删一次。 conn.delete(‘img_%s’%uuid)

2:注册接口补充:
在这里插入图片描述

# 验证码业务流程:
        # 连接数据库,在数据库中查询出验证码,如果没有查到,说明验证码过期了。
        # 如果验证码和用户输入不一致则验证码输入错误。
        conn = get_redis_connection("verify_code")
        sms_code_from_redis = conn.get("sms_%s" % mobile)
        if not sms_code_from_redis:
            return JsonResponse({
                "code":400,
                "errmsg": "验证码过期",
            }, status=403)
        
        if sms_code_from_redis != sms_code:
            return JsonResponse({
                "code": 400,
                "errmsg": "验证码错误",
            }, status=400)

3:图形验证码忽略大小写:

 if image_code.lower() != image_code_from_redis.lower(): # 全部转为小写比较,目的是忽略大小写
            return JsonResponse({
                'code': 400,
                'errmsg': '验证码输入有误'
            }, status=400)

4:避免频繁发送验证码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


posted on 2020-09-02 23:38  飞行的猪哼哼  阅读(50)  评论(0)    收藏  举报