联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

Flutter+python实现验证码登录

作者:访客发布时间:2023-12-26分类:程序开发学习浏览:90


导读:实现思路前端(Flutter应用)的工作:收集用户信息:用户输入手机号码,前端收集这个信息。发送请求到后端:当用户点击发送验证码按钮时,前端向后端发送一个包含手机号...

实现思路

前端(Flutter应用)的工作:

  1. 收集用户信息

    • 用户输入手机号码,前端收集这个信息。
  2. 发送请求到后端

    • 当用户点击发送验证码按钮时,前端向后端发送一个包含手机号码的请求。
  3. 接收后端响应

    • 根据后端的响应,前端显示相应的信息给用户,比如“验证码发送成功”或“发送失败”。
  4. 收集验证码输入

    • 用户收到短信后,将验证码输入到前端界面。
  5. 提交验证码进行验证

    • 用户提交验证码后,前端将手机号码和验证码一起发送到后端进行验证。

后端的工作:

  1. 接收来自前端的请求

    • 后端接收来自前端的包含手机号码的请求。
  2. 生成验证码

    • 后端生成一个随机的验证码。
  3. 调用短信服务API发送验证码

    • 后端调用阿里云短信服务API,将验证码发送到用户的手机号码。
  4. 存储验证码

    • 后端暂时存储验证码及其相关信息(如手机号、过期时间等),以便稍后验证。
  5. 响应前端

    • 后端向前端发送响应,表示验证码是否发送成功。
  6. 接收并验证验证码

    • 当用户提交验证码时,后端接收手机号码和验证码,验证验证码的正确性。
  7. 返回验证结果

    • 后端返回验证结果给前端,如“验证成功”或“验证失败”。

前期准备工作

我使用的是阿里云短信服务,在调用短信API之前,要完成以下工作:

  1. 申请产品试用
  • 在阿里云通信产品免费试用申请免费产品试用,我是个人用户,因此申请的第一个

image.png 2. 定义模板和签名

  • 在短信服务中心完成模板和签名的申请。模板和签名定义了你收到短信的内容,这一步可以不进行,阿里云提供了专用的测试模板和签名,可以直接使用

Pasted image 20231225125049.png 3. 添加测试手机号

Pasted image 20231225125415.png 4. 获取AccessKey ID 和 AccessKey Secret

  • 点击右上角头像,点击AccessKey管理,点击创建AccessKey按钮,创建新的AccessKey,记得保存好AccessKey ID 和 AccessKey Secret

Pasted image 20231225125956.png

前端代码

界面代码

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

标签:验证码Flutterpython


程序开发学习排行
最近发表
网站分类
标签列表