Python+Django+阿里云验证码短信登录(全网最最最详细)

最终实现:
验证码登录

首先需要在阿里云平台注册一个账号

注册好账号在输入框中搜索:
在这里插入图片描述
然后进入之后点击快速学习和测试,这一步其实不操作也可以在这里插入图片描述
现在出来了资质管理,第一步就是要填这部分的内容
在这里插入图片描述
按需填写申请,一般是有俩小时审核期,所以可能要等半天时间才能搞的差不多
在这里插入图片描述

和上面同理填写内容申请:
在这里插入图片描述
截图属实麻烦,本来想写个从头到尾的操作的,实在不想搞,大家可以参考:
超详细阿里云平台操作

实现Django成功连接阿里云短信服务

实现代码的逻辑

1)前端form表单中输入电话号码后,点击发送,触发后端的发送验证码功能。
2)后端先解析电话号码是否合理,如果合理,则随机生成一个验证码,并使用阿里云的短信发送接口将验证码发送到该手机。并将手机号和验证码存到Mysql数据库中
3)前端用户收到短信后,在表单中填入验证码,点击登录按钮后触发后端的登录api。同时后端将收到的验证码,与Msql库中存的验证码进行比对,如果一致则合理,返回token及用户信息到前端。

创建utils_sms.py

  1. 安装阿里云 Python SDK
    阿里云提供了一个 aliyun-python-sdk-core 包用于核心功能,以及一个 aliyun-python-sdk-dysmsapi 包用于短信服务。你可以使用以下命令来安装这两个包:

    pip install aliyun-python-sdk-core
    pip install aliyun-python-sdk-dysmsapi
    
    
    #utlis_sms.py
    		from 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
    		def create_client(access_key_id, access_key_secret):
    		    config = open_api_models.Config(
    		        access_key_id=access_key_id,
    		        access_key_secret=access_key_secret
    		    )
    		    config.endpoint = f'dysmsapi.aliyuncs.com'
    		    return Dysmsapi20170525Client(config)
    
    def send_sms(phone_number,code):
        client = create_client('your_access_key_id', 'your_access_key_secret')
        send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
            sign_name='***',
            template_code='***',
            phone_numbers=phone_number,
            # template_param='{"code":"4567"}'
            template_param='{"code":"' + str(code) + '"}'
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 复制代码运行请自行打印 API 的返回值
            response=client.send_sms_with_options(send_sms_request, runtime)
            return response
        except Exception as error:
            print(str(error))
            return None
    

models.py

class VerificationCode(models.Model):
    phone_number = models.CharField(max_length=15)
    code = models.CharField(max_length=6)
    created_at = models.DateTimeField(default=timezone.now)

    def is_valid(self):
        # 验证码有效期设置为5分钟
        expiration_time = self.created_at + timedelta(minutes=5)
        return timezone.now() <= expiration_time

不要忘记重新生成迁移文件

	#python manage.py makemigrations
	#python manage.py migrate

后端调用

def number_login(request):
    return render(request,'number_login.html')
@csrf_exempt
def send_code(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        phone_number = data.get('phone_number')

        # 有效电话号码
        if not re.match(r'^\+?\d{10,15}$', phone_number):
            return JsonResponse({'message': '无效的电话号码'}, status=400)

        # 随机生成6位数的验证码
        code = str(random.randint(100000, 999999))
        #将手机号和验证码存到数据库的表中
        VerificationCode.objects.create(phone_number=phone_number, code=code)
        #通过阿里云给用户发短信
        if send_sms(phone_number, code):
            return JsonResponse({'message': '验证码发送成功'})
        else:
            return JsonResponse({'message': '验证码发送失败'}, status=500)
    return JsonResponse({'message': '无效的请求方法'}, status=405)


@csrf_exempt
def verify_code(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        phone_number = data.get('phone_number')
        code = data.get('code')

        try:
        #访问数据库查看手机号和验证码
            verification = VerificationCode.objects.get(phone_number=phone_number, code=code)
            if verification.is_valid():
            #通过token进行验证前端的验证码和数据库中的验证码是否一致
                # Generate a token (dummy example here)
                token = 'example_token_12345'
                return JsonResponse({'success': True, 'token': token})
            else:
                return JsonResponse({'success': False, 'message': '验证码已过期'}, status=400)
        except VerificationCode.DoesNotExist:
            return JsonResponse({'success': False, 'message': '无效的验证码'}, status=400)
    return JsonResponse({'message': '无效的请求方法'}, status=405)

前端

number_login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手机号验证码登录</title>

 		{% load static %}
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.css' %}">
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.js' %}"></script>
<style>
    body {
        background-image: url("{% static 'img/your_background.png'%}");
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        margin: 0;
        padding: 0;
        height: 100vh;
    }
    .c1 {
        width: 500px;
        height:500px;
        border: 1px solid #dddddd;
        border-radius: 5px;
        margin: 200px auto;
        padding: 40px 40px;
        box-shadow: 5px 5px 5px  #aaa;
        background-color: white;
        }
        此处有省略css,可以根据自己喜欢的调整页面布局
</style>
</head>
	<body>
	<div class="c1">
	    <div class="ant-tabs-nav-list">
	        <div class="ant-tabs-tab ant-tabs-tab-active">
	            <div role="tab" aria-selected="true" class="ant-tabs-tab-btn" tabindex="0" id="rc-tabs-0-tab-code-login" aria-controls="rc-tabs-0-panel-code-login">
	                <a href="/user/login/">密码登录</a>
	            </div>
	        </div>
	        <div class="ant-tabs-tab">
	            <div role="tab" aria-selected="false" class="ant-tabs-tab-btn" tabindex="0" id="rc-tabs-0-tab-number-login" aria-controls="rc-tabs-0-panel-number-login">
	                <a href="/number/login/">手机号登录</a>
	            </div>
	        </div>
	    </div>
	    <form id="verification-form">
	        <div class="form-group">
	            <label for="phone-number">手机号</label>
	            <input type="text" id="phone-number" class="form-control" placeholder="请输入手机号" required>
	        </div>
	        <button type="button" onclick="sendCode()" class="btn btn-primary">发送验证码</button>
	    </form>
	    <form id="code-form" style="margin-top: 20px;">
	        <div class="form-group">
	            <label for="code">验证码</label>
	            <input type="text" id="code" class="form-control" placeholder="请输入验证码" required>
	        </div>
	        <button type="button" onclick="verifyCode()" class="btn btn-primary">登录</button>
	    </form>
	</div>
	
<script>
    async function sendCode() {
        const phoneNumber = document.getElementById('phone-number').value;
        const response = await fetch('/send_code/', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': getCsrfToken()
            },
            body: JSON.stringify({ phone_number: phoneNumber })
        });
        const data = await response.json();
        alert(data.message);
    }

    async function verifyCode() {
        const phoneNumber = document.getElementById('phone-number').value;
        const code = document.getElementById('code').value;
        const response = await fetch('/verify_code/', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': getCsrfToken()
            },
            body: JSON.stringify({ phone_number: phoneNumber, code: code })
        });
        const data = await response.json();
        if (data.success) {
            window.location.href = '/index/';
        } else {
            alert('Verification failed: ' + data.message);
        }
    }

    function getCsrfToken() {
        let csrfToken = null;
        const cookies = document.cookie.split(';');
        cookies.forEach(cookie => {
            const [name, value] = cookie.split('=');
            if (name.trim() === 'csrftoken') {
                csrfToken = value;
            }
        });
        return csrfToken;
    }
</script>
</body>
</html>

总结

每个人写代码的习惯都不一样,但是整体的思路应该是一样的,强烈建议思考我写的实现代码逻辑那部分内容,然后以代码为辅,帮助小伙伴们解决难题。如果看这篇文章有难以让你理解的地方,请留言评论,最近比较活跃,我看到的话会及时回复。

要使用阿里云短信服务在Django中发送短信,需要先注册阿里云账号并开通短信服务。然后按照以下步骤进行操作: 1. 安装阿里云Python SDK。 2. 在Django项目的settings.py文件中添加以下配置: ``` ALIYUN_ACCESS_KEY_ID = '<AccessKeyId>' ALIYUN_ACCESS_KEY_SECRET = '<AccessKeySecret>' ALIYUN_SMS_SIGN_NAME = '<短信签名>' ALIYUN_SMS_TEMPLATE_CODE = '<短信模板编号>' ``` 其中,<AccessKeyId>和<AccessKeySecret>是阿里云提供的访问密钥,<短信签名>和<短信模板编号>是需要提前创建的。 3. 创建一个发送短信的函数,如下所示: ```python from aliyunsdkcore.client import AcsClient from aliyunsdkcore.request import CommonRequest def send_sms(phone_numbers, template_param): client = AcsClient(ALIYUN_ACCESS_KEY_ID, ALIYUN_ACCESS_KEY_SECRET, 'cn-hangzhou') request = CommonRequest() request.set_method('POST') request.set_domain('dysmsapi.aliyuncs.com') 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', ALIYUN_SMS_SIGN_NAME) request.add_query_param('TemplateCode', ALIYUN_SMS_TEMPLATE_CODE) request.add_query_param('TemplateParam', template_param) response = client.do_action(request) return response ``` 其中,phone_numbers是接收短信的手机号码,template_param是短信模板中需要替换的参数。 4. 在需要发送短信的地方调用send_sms函数即可。 注意:使用阿里云短信服务需要按照相关规定使用,不能发送垃圾短信或违法信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值