准备:
1.容联云通信注册账号并下载设置
2.将yuntongxun文件夹复制到项目目录下
短信验证码业务分析: 需要使用redis数据库 配置文件里添加如下设置
CACHES = { "default": { # 默认的缓存配置 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/0", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, # 我的需求是希望将session存储在redis的1号库 "session": { # session后端 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, "verify_code": { # 验证码 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, }
短信验证码后端接口设计:
1.请求方式 选项 方案 请求方法 GET 请求地址 /sms_codes/(?P<mobile>1[3-9]\d{9})/ 请求参数:路径参数和查询字符串传参 其中:mobile 是用路径传递参数的, image_code 和 image_code_id 是用查询字符串传递的参数. 2.参数名 类型 是否必传 说明 mobile string 是 手机号 image_code string 是 图形验证码 image_code_id string 是 唯一编号 3.响应结果:JSON 字段 说明 code 状态码 errmsg 错误信息
短信验证码实现 在视图集文件里添加代码
class SMSCodeView(View): def get(self, reqeust, mobile): # 避免频繁发送短信验证码 redis_conn = get_redis_connection(\'verify_code\') send_flag = redis_conn.get(\'send_flag_%s\' % mobile) if send_flag: return http.JsonResponse({\'code\': 400, \'errmsg\': \'发送短信过于频繁\'}) image_code_client = reqeust.GET.get(\'image_code\') uuid = reqeust.GET.get(\'image_code_id\') if not all([image_code_client, uuid]): return http.JsonResponse({\'code\': 400, \'errmsg\': \'缺少必传参数\'}) image_code_server = redis_conn.get(\'img_%s\' % uuid) if image_code_server is None: return http.JsonResponse({\'code\': 400, \'errmsg\': \'图形验证码失效\'}) try: redis_conn.delete(\'img_%s\' % uuid) except Exception as e: logger.error(e) image_code_server = image_code_server.decode() if image_code_client.lower() != image_code_server.lower(): return http.JsonResponse({\'code\': 400, \'errmsg\': \'输入图形验证码有误\'}) sms_code = \'%06d\' % random.randint(0, 999999) logger.info(sms_code) # 创建管道对象: pl = redis_conn.pipeline() # redis_conn.setex(\'sms_%s\' % mobile, 300, sms_code) pl.setex(\'sms_%s\' % mobile, 300, sms_code) # redis_conn.setex(\'send_flag_%s\' % mobile, 60, 1) pl.setex(\'send_flag_%s\' % mobile, 60, 1) # 执行管道: pl.execute() CCP().send_template_sms(mobile, [sms_code, 5], 1) return http.JsonResponse({\'code\': 0, \'errmsg\': \'发送短信成功\'})
配置短信验证码的url
urlpatterns = [ re_path(r"^sms_codes/(?P<mobile>1[3-9]\d{9})/$", views.SMSCodeView.as_view()), ]
短信验证码后端常见优化:
1. 如何避免频繁发送短信验证码: 在后端也要限制用户请求短信验证码的频率. 60秒内只允许一次请求短信验证码. 在 Redis 数据库中缓存一个数值,有效期设置为60秒. 2. Redis服务端问题: 如果Redis服务端需要同时处理多个请求,加上网络延迟, 那么服务端利用率不高,效率降低。 解决方案:pipeline 1. 创建redis请求管道 2. 将操作redis的多个命令请求添加到管道队列里 3. 执行命令 3.发送短信是耗时操作,如果短信被阻塞,用户响应会延迟,影响用户界面倒计时延迟 """ CCP().send_template_sms(mobile, [sms_code, 5], 1) return http.JsonResponse({\'code\': 0, \'errmsg\': \'发送短信成功\'}) """ 解决方案:异步方案redis 和 Celey 异步发送短信 将发送短信业务和响应分开执行,将发送短信 从主业务中 解耦出来