Flutter+python实现验证码登录
作者:访客发布时间:2023-12-26分类:程序开发学习浏览:90
导读:实现思路前端(Flutter应用)的工作:收集用户信息:用户输入手机号码,前端收集这个信息。发送请求到后端:当用户点击发送验证码按钮时,前端向后端发送一个包含手机号...
实现思路
前端(Flutter应用)的工作:
-
收集用户信息:
- 用户输入手机号码,前端收集这个信息。
-
发送请求到后端:
- 当用户点击发送验证码按钮时,前端向后端发送一个包含手机号码的请求。
-
接收后端响应:
- 根据后端的响应,前端显示相应的信息给用户,比如“验证码发送成功”或“发送失败”。
-
收集验证码输入:
- 用户收到短信后,将验证码输入到前端界面。
-
提交验证码进行验证:
- 用户提交验证码后,前端将手机号码和验证码一起发送到后端进行验证。
后端的工作:
-
接收来自前端的请求:
- 后端接收来自前端的包含手机号码的请求。
-
生成验证码:
- 后端生成一个随机的验证码。
-
调用短信服务API发送验证码:
- 后端调用阿里云短信服务API,将验证码发送到用户的手机号码。
-
存储验证码:
- 后端暂时存储验证码及其相关信息(如手机号、过期时间等),以便稍后验证。
-
响应前端:
- 后端向前端发送响应,表示验证码是否发送成功。
-
接收并验证验证码:
- 当用户提交验证码时,后端接收手机号码和验证码,验证验证码的正确性。
-
返回验证结果:
- 后端返回验证结果给前端,如“验证成功”或“验证失败”。
前期准备工作
我使用的是阿里云短信服务,在调用短信API之前,要完成以下工作:
- 申请产品试用
- 在阿里云通信产品免费试用申请免费产品试用,我是个人用户,因此申请的第一个
2. 定义模板和签名
- 在短信服务中心完成模板和签名的申请。模板和签名定义了你收到短信的内容,这一步可以不进行,阿里云提供了专用的测试模板和签名,可以直接使用
3. 添加测试手机号
4. 获取AccessKey ID 和 AccessKey Secret
- 点击右上角头像,点击AccessKey管理,点击创建AccessKey按钮,创建新的AccessKey,记得保存好AccessKey ID 和 AccessKey Secret
前端代码
界面代码
class Sms extends StatefulWidget {
const Sms({super.key});
@override
State<Sms> createState() => _SmsState();
}
class _SmsState extends State<Sms> {
final TextEditingController _phoneController = TextEditingController();
final TextEditingController _codeController = TextEditingController();
bool _isButtonDisabled = true;
bool _isCodeSent = false;
int _countdown = 60;
final SmsController _smsController = SmsController();
void _updateState() {
setState(() {
_isCodeSent = true;
_startCountdown();
});
}
void _startCountdown() {
Future.delayed(Duration(seconds: 1), () {
if (_countdown > 0) {
setState(() {
_countdown--;
});
_startCountdown();
} else {
setState(() {
_isCodeSent = false;
_countdown = 60;
});
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('验证码登录')),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'使用验证码登录',
textAlign: TextAlign.center,
style: TextStyle(fontSize: MediaQuery.of(context).size.width * 0.05),
),
SizedBox(height: 20),
Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _phoneController,
decoration: InputDecoration(hintText: '输入手机号'),
keyboardType: TextInputType.phone,
),
),
TextButton(
child: _isCodeSent
? Text('重发($_countdown)')
: Text('发送验证码'),
onPressed: _isCodeSent ? null : () async {
await _smsController.sendCode(
_phoneController.text, context, _updateState);
},
),
],
),
TextField(
controller: _codeController,
decoration: InputDecoration(hintText: '输入验证码'),
onChanged: (value) {
setState(() {
_isButtonDisabled = value.isEmpty;
});
},
),
SizedBox(height: 20),
ElevatedButton(
child: Text('登录'),
onPressed: _isButtonDisabled ? null : () async {
await _smsController.verifyCodeAndLogin(
_phoneController.text, _codeController.text, context);
},
),
],
),
),
);
}
}
在界面这部分我引用了smsController类中的两个方法,在这两个方法中我调用后端接口,分别实现了发送验证码,以及验证验证码的功能。代码如下:
class SmsController {
Future<void> verifyCodeAndLogin(String phoneNumber, String code, BuildContext context) async {
final response = await http.post(
//后端接口,替换你的后端接口
Uri.parse('http://000.000.0000.000/verify_code'),
headers: <String, String>{
'Content-Type': 'application/json',
},
body: jsonEncode(<String, String>{
'phone_number': phoneNumber,
'code': code,
}),
);
if (response.statusCode == 200) {
Navigator.pushNamed(context, '/index');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('手机号或验证码错误')),
);
}
}
Future<void> sendCode(String phoneNumber, BuildContext context, Function updateState) async {
if (phoneNumber.length == 11) {
final response = await http.post(
//后端接口,替换你的后端接口
Uri.parse('http://000.000.0000.000/send_verification_sms'),
headers: <String, String>{
'Content-Type': 'application/json',
},
body: jsonEncode(<String, String>{
'phone_number': phoneNumber,
}),
);
if (response.statusCode == 200) {
updateState();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('验证码已成功发送')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('验证码发送失败')),
);
}
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('手机号格式错误')),
);
}
}
}
后端代码使用python实现,代码如下
@app.route('/send_verification_sms', methods=['POST'])
async def send_verification_sms():
phone_number = (await request.get_json()).get('phone_number')
if not phone_number:
return jsonify({"error": "Phone number is required"}), 400
sign_name = "阿里云短信测试" # Replace with your sign name
#输入你的模板code
template_code = ""
try:
response = send_sms(phone_number, sign_name, template_code)
return jsonify({"message": "SMS sent successfully", "response": str(response)})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/verify_code', methods=['POST'])
async def verify_sms_code():
json_data = await request.get_json()
phone_number = json_data.get('phone_number')
code = json_data.get('code')
if verify_code(phone_number, code):
return jsonify({"message": "Verification successful"})
else:
return jsonify({"error": "Invalid or expired code"}), 400
#输入你的ACCESS_KEY_ID和ACCESS_KEY_SECRET
ACCESS_KEY_ID = ""
ACCESS_KEY_SECRET = ""
client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, 'cn-hangzhou')
def send_sms(phone_numbers, sign_name, template_code):
request = CommonRequest()
request.set_accept_format('json')
request.set_domain('dysmsapi.aliyuncs.com')
request.set_method('POST')
request.set_protocol_type('https') # https | http
request.set_version('2017-05-25')
request.set_action_name('SendSms')
request.add_query_param('RegionId', "cn-hangzhou")
request.add_query_param('PhoneNumbers', phone_numbers)
request.add_query_param('SignName', sign_name)
request.add_query_param('TemplateCode', template_code)
verification_code = generate_verification_code()
params = f"{{\"code\":\"{verification_code}\"}}"
request.add_query_param('TemplateParam', params)
# 保存验证码和时间戳
with shelve.open('verification_codes.db') as db:
db[phone_numbers] = {'code': verification_code, 'timestamp': datetime.now()}
response = client.do_action_with_exception(request)
return response
def verify_code(phone_number, code):
with shelve.open('verification_codes.db') as db:
if phone_number in db:
data = db[phone_number]
# 检查验证码是否匹配且未过期(5分钟)
if data['code'] == code and datetime.now() - data['timestamp'] <= timedelta(minutes=5):
return True
return False
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版