阿里云验证码短信发送服务搭建(flask)

参考:https://next.api.aliyun.com/api-tools/sdk/Dysmsapi?version=2017-05-25&language=java-async-tea&tab=primer-doc

我们需要思考验证服务一些要求:

1.验证码只能被验证一次,所以需要状态字段
2.验证码有失效时间,超出时间后则失效
3.验证码有限制次数,比如1min只能发送一次,1h只能发送xx次,一天只能发送xx次
4.验证码由random包生成四位随机数字

因此,我们创建数据表

CREATE TABLE `verification_code` (`id` int NOT NULL AUTO_INCREMENT,`phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '手机号码',`code` varchar(6) DEFAULT '' COMMENT '验证码',`channel` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '渠道名称',`template_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '模板代码',`status` tinyint DEFAULT '10' COMMENT '状态',`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`type` tinyint DEFAULT '1' COMMENT '类型 1:验证码短信 2:通知短信',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

项目结构如下:
在这里插入图片描述

web.py是我们的主文件

注意作者此处使用了数据库操作方法更改状态,读者可以使用redis等数据库操作

from datetime import datetime, timedeltafrom flask import request, jsonify
import randomfrom utils import Sample
from my_app.crud.crud_SMS import CRUDSMSapp = Flask(__name__)# 统一响应数据格式
def response(code=200, message="请求成功!", data=None):res = {'code': code,'message': message,'data': data if data is not None else {}}return jsonify(res)# 定义一个错误处理器,捕获所有的异常
@app.errorhandler(Exception)
def handle_error(e):return response(400, str(e))@app.route('/sms_message/verify_code', methods=['POST'])
def verify():data = request.get_json()phone = data.get('phone')code = data.get('code')channel = data.get('channel')result = CRUDSMS.get(phone, channel)current_time = datetime.now()# 判断 验证码是否有效if result:if current_time - result['create_time'] > timedelta(minutes=5):return response(401, message="验证码已过期")# 验证码是否正确if code == result['code']:if result['status'] == 99:return response(401, message="验证码已被验证过了,请勿重复使用")else:CRUDSMS.update(result["id"],{"status":99}) #过期失效return response(200, message="验证成功")else:return response(405, message="验证码错误")else:return response(406, message="该手机未发送过验证码")@app.route('/sms_message/getVerificationCode', methods=['POST'])
def getVerificationCode():data = request.get_json()channel = data.get('channel')phone = data.get('phone')# 随机生成四位数字random_number_str = ''.join([str(random.randint(0, 9)) for _ in range(4)])template_code = "xxx"result = CRUDSMS.get(phone, channel)current_time = datetime.now()# 判断 验证码是在1min之内发送过if result and current_time - result['create_time'] < timedelta(minutes=1):return response(401, message="短信1分钟之内已经发送过,请稍后再试")# 判断用户最近一小时发过几次短信# 计算过去 1 小时的时间点one_hour_ago = current_time - timedelta(hours=1)one_day_ago = current_time - timedelta(days=1)past_hour_message_num = CRUDSMS.count(phone, channel, one_hour_ago)past_day_message_num = CRUDSMS.count(phone, channel, one_day_ago)if past_hour_message_num > 5:return response(402, message="短信1小时之内已经发送过5条,超出上限,请稍后再试")if past_day_message_num > 10:return response(403, message="短信1天之内已经发送过10条,超出上限,请稍后再试")result = Sample.getVerificationCode(template_code, phone, random_number_str)if result:CRUDSMS.create({"type": 1, "channel": channel, "phone": phone, "code": random_number_str, "template_code": template_code,"create_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')})return response(200, data=random_number_str)return response(400, message="短信发送失败")@app.route('/sms_message/sendNotice', methods=['POST'])
def sendNotice():# 从请求中获取union_iddata = request.get_json()template_code = data.get('template_code')channel = data.get('channel')template_param = data.get('template_param','')phone = data.get('phone')result = Sample.sendNotice(template_code, phone, template_param)if result:# 存入数据库CRUDSMS.create({"type": 2, "channel": channel, "phone": phone, "code": "", "template_code": template_code,"create_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')})return response(200)return response(400, message="短信发送失败")if __name__ == '__main__':app.run(debug=True, host="0.0.0.0", port=5000)

utils.py文件是操作阿里云接口的方法:
填写sign_name、 ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET

# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import os
import sysfrom typing import Listfrom alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from logger import normal_log,error_log
ALIBABA_CLOUD_ACCESS_KEY_ID = ""
ALIBABA_CLOUD_ACCESS_KEY_SECRET = ""
class Sample:def __init__(self):pass@staticmethoddef create_client() -> Dysmsapi20170525Client:"""使用AK&SK初始化账号Client@return: Client@throws Exception"""# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。# 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html。config = open_api_models.Config(# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。,access_key_id=ALIBABA_CLOUD_ACCESS_KEY_ID,# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。,access_key_secret=ALIBABA_CLOUD_ACCESS_KEY_SECRET)# Endpoint 请参考 https://api.aliyun.com/product/Dysmsapiconfig.endpoint = f'dysmsapi.aliyuncs.com'return Dysmsapi20170525Client(config)@staticmethoddef getVerificationCode(template_code,phone_numbers,code):client = Sample.create_client()send_sms_request = dysmsapi_20170525_models.SendSmsRequest(phone_numbers=phone_numbers,sign_name='xxx',template_code = template_code,template_param  = '{"code":"%s"}'%code,)try:# 复制代码运行请自行打印 API 的返回值client.send_sms_with_options(send_sms_request, util_models.RuntimeOptions())normal_log.logger.info("{} 发送验证码成功".format(phone_numbers))return Trueexcept Exception as error:# 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。# 错误 messageprint("{} 发送验证码失败{}".format(phone_numbers, str(error)))return False@staticmethoddef sendNotice(template_code, phone_numbers,template_param):client = Sample.create_client()send_sms_request = dysmsapi_20170525_models.SendSmsRequest(phone_numbers=phone_numbers,sign_name='',template_code=template_code,template_param=template_param)try:# 复制代码运行请自行打印 API 的返回值client.send_sms_with_options(send_sms_request, util_models.RuntimeOptions()) return Trueexcept Exception as error:...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/57218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++STL--------list

文章目录 一、list链表的使用1、迭代器2、头插、头删3、insert任意位置插入4、erase任意位置删除5、push_back 和 pop_back()6、emplace_back尾插7、swap交换链表8、reverse逆置9、merge归并10、unique去重11、remove删除指定的值12、splice把一个链表的结点转移个另一个链表13…

利用Spring Boot实现信息化教学平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理信息化在线教学平台的相关信息成为必然。开…

AI金融攻防赛:YOLO理论学习及赛题进阶思路(DataWhale组队学习)

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月学习赛的AI金融攻防赛学习总结文档。本文主要讲解如何在金融场景凭证篡改检测中应用YOLO算法。我们将从模型概述、数据准备、训练流程以及模…

互联网数字化商品管理浪潮思考:从信息化到精准运营

目录 一、商品数字化转型面临的现状分析 &#xff08;一&#xff09;运营方向分析 &#xff08;二&#xff09;商品归类分析 二、商品数字化管理建设分析 三、基础建设——商品信息数字化 &#xff08;一&#xff09;商品信息质量数字化的目的 &#xff08;二&#xff0…

[k8s理论知识]3.docker基础(二)隔离技术

容器其实是一种沙盒技术&#xff0c;其核心是通过约束和修改进程的动态表现&#xff0c;为其创建一个边界。这个边界确保了应用与应用之间不会相互干扰&#xff0c;同时可以方便在不同的环境中迁移&#xff0c;这是PaaS最理想的状态。 程序是代码的可执行镜像&#xff0c;通常…

探索Spring Cloud Config:构建高可用的配置中心

目录 认识Spring Cloud ConfigConfig Server读取配置文件步骤1&#xff1a;&#xff08;1&#xff09;创建config-server项目&#xff08;2&#xff09;在config-server中开启Config Server功能&#xff08;3&#xff09;在config-server配置文件进行相关配置&#xff08;4&…

Axure复选框全选反选取消高级交互

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;复选框全选反选取消制作 主要内容&#xff1a;点击复选框&#xff0c;实现列表数据项全选选中、反选和取消选中效果 应用场景&#xff1a;多项选定…

【MySQL 保姆级教学】表的增删改查(上)

表的增删改查 1. 创建一个表 CREATE2 插入数据 INSERT INTO2.1 语法2.2 插入单行数据全列插入2.3 插入多行数据指定列插入2.4 同步更新 ON DUPLICATE KEY UPDATE2.4.1 引入2.4.2 同步更新2.4.3 查看被影响的行 2.5. 替换 REPLACE INTO 3. Retrieve&#xff08;查询SELECT&#…

有道在线翻译+4款新星,翻译从此无障碍,你get了吗?

现在全世界都连在一起了&#xff0c;说话不一样的问题再也不是啥大事。不管是搞研究、谈生意还是平时过日子&#xff0c;翻译软件都成了我们离不开的帮手。今儿&#xff0c;我们特激动地告诉大家&#xff0c;有道在线翻译和三个新伙伴一起&#xff0c;给Windows系统做了个超牛的…

9.校园二手网站系统( Springboot 和 thymeleaf(html)开源框架)

目录 1.系统的受众说明 2.系统需求分析 2.2.1用户功能模块 2.2.2二手交易功能需求 2.2.3需求发布功能需求 2.3.1操作流程 2.3.2添加信息流程 2.3.3删除信息流程 2.4 系统E-R图 3.系统概要设计 3.1系统的整体架构 3.2 数据库表 4.系统实现 4.1用户功能模块 4.2 二…

程序员们辛苦啦!1024程序员节,今天,我们不一样!

一、程序员节来历 程序员节&#xff08;Programmers Day&#xff09;是一年中专门为程序员和计算机科学工作者所设立的节日&#xff0c;通常是在每年的第256天庆祝。256这个数字在编程中具有特别的意义&#xff0c;因为它是2的8次方&#xff0c;代表着一个字节可以表示的所有可…

如何借助前端表格控件助力企业实现财务数字化转型

最新技术资源&#xff08;建议收藏&#xff09; https://www.grapecity.com.cn/resources/ 前言 在当今快速变化的经济环境中&#xff0c;记账软件对个人和企业的重要性愈发突出。对于个人而言&#xff0c;它可以帮助用户实时掌握财务状况&#xff0c;促进合理消费和有效储蓄&…

Java项目-基于Springboot的高校党务系统项目(源码+说明).zip

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

【SoC_Design】USB基本知识

目录 USB物理接口 USB3.0物理层支持dp-alt的usb type-c接口 拓扑结构层次结构 USB物理接口 USB2.0 两线&#xff1a;D、D- USB3 六线&#xff1a;D、D-、SSTX、SSTX-、SSRX、SSRX- USB3 2lane 十线&#xff1a; D、D-、&#xff08;SSTX、SSTX-、SSRX、SSRX-&#xff09;x2USB2…

CSS文本基础知识

1、文本缩进 属性名&#xff1a;text-indent 属性值&#xff1a;数值px&#xff1b; 数字em&#xff08;推荐&#xff1a;1em当前标签的字号大小&#xff09; 例&#xff1a;代码&#xff1a; 结果: 2、文本对齐方式 作用&#xff1a;控制内容水平方式 属性名&#xff1a…

公众号变现及生财内参项目建议

一、核心内容 &#xff08;一&#xff09;公众号变现分享 从业者王薄荷介绍公众号常规盈利思路为推文广告和品牌广告&#xff0c;公众号能外链的地方有菜单栏和阅读原文&#xff0c;虽菜单栏点击率低但有商业价值。以小说为例&#xff0c;主要盈利方式是小黄文截止在高潮部分…

HTB:Knife[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are open on Knife? 2.What version of PHP is running on the webserver? 并没有我们需要的信息&#xff0c;接着使用浏览器访问靶机80端口 尝试使用ffuf对靶机Web进行一下目录FUZZ 使用curl访问该文件获取HTTP头…

聚焦IOC容器刷新环节postProcessBeanFactory(BeanFactory后置处理)专项

目录 一、IOC容器的刷新环节快速回顾 二、postProcessBeanFactory源码展示分析 &#xff08;一&#xff09;模版方法postProcessBeanFactory &#xff08;二&#xff09;AnnotationConfigServletWebServerApplicationContext 调用父类的 postProcessBeanFactory 包扫描 …

React综合指南(二)

https://activity.csdn.net/creatActivity?id10787 #1024程序员节&#xff5c;征文# 21、 React中的状态是什么&#xff1f;它是如何使用的&#xff1f;&#xff1f; 状态是 React 组件的核心&#xff0c;是数据的来源&#xff0c;必须尽可能简单。基本上状态是确定组件呈现…

rk3568 android11 单独烧写内核。

问题: 我现在 遇到一个问题,如果我单独 烧写boot.img 的话,就会进入 recovery 的模式。 如下图: 问题说明: 如果我烧写的 Update.img 是可以启动的。那么我再烧写一个 编译 update.img 顺带编译出来的 boot.img 是可以正常启动的。 问题出在 , 如果我 重新编译一遍 ,使…