图片验证及短信验证

14 篇文章 1 订阅
5 篇文章 0 订阅

图片验证及短信校验

1. 图片验证码

​ 这种图片验证方式是我们最常见的形式,它可以有效的防范恶意攻击者采用恶意工具,调用“动态验证码短信获取”接口进行动态短信发送, 导致接入用户短信被刷,造成账号余额损失。同时这种动态发送方式会朝许多无关的手机用户,发送很多验证码短信,导致手机用户被骚扰,甚至引起用户投诉。这种恶意攻击究其原因是攻击者可以自动对接口进行大量调用。

如果网站在用户进行“动态验证码短信发送” 操作前,要求用户输入图片验证码,确认用户是真实有效后,服务器端再发送动态短信到用户手机上。这一种流程就可以有效的解决恶意攻击问题。正确的加入图片验证码的方式是在短信验证码发送前,先让用户填写图片验证码,再发送短信验证码。

Uuid, 唯一身份标识码, 在用户注册之前,网站没有任何东西来区分 不同的 客户端, 因此 在客户端 生成 一个 uuid, django中通过不同的uuid 来 区分 不同的客户端

2. 图片验证码生成与展示
django
#1.在项目主目录下新建utils文件夹,下载captcha文件夹,放到utils下
#2.写生成验证码接口
from utils.captcha.captcha import captcha
#生成图片验证码
class ImageCodeAPIView(APIView):
    def get(self,request):
        name,text,pic = captcha.generate_captcha()
        return HttpResponse(pic, content_type='image/jpg')
      
路由
from django.urls import path, re_path
from user.views import *

urlpatterns = [
    path('image_code/', ImageCodeAPIView.as_view()),
]
Django-redis使用

1、安装

pip install django-redis

2、配置redis

# setting.py
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

3、redis连接封装

utils下面新建一个common.py文件

#redis连接
def get_redis_conn():
    from django_redis import get_redis_connection
    conn = get_redis_connection()
    return conn

验证码图片redis存储

from utils import comm

#生成图片验证码
class GetCaptcha(APIView):
    def get(self,request):
        #获取uuid
        uuid = request.GET.get('uuid')
        #生成验证码图片
        name,text,pic = captcha.generate_captcha()
        #获取redis连接
        redis_con = comm.get_redis_conn()
        #图片验证码存储在redis里面,设置过期时间
        redis_con.setex(uuid, 60, text) #以秒为单位
        #以图片的方式输出
        return HttpResponse(pic, content_type='image/jpg')
vue
  • 定义方法
    • 生成uuid
    • 将 uuid拼接到请求网址中,生成 图片验证码的url
  • 将拼接好的图片验证码url绑定到image标签中
  • 初始加载页面时,需要 在 钩子函数中挂载方法
  • 定义图片的点击事件,触发方法,生成新的uuid,重新请求图片
<!--  4. 对img标签进行属性绑定          -->
<img :src="image_code_url" alt="图形验证码" class="pic_code">
<!--  5. 对img标签进行点击事件绑定 ,点击一次,执行一次方法,请求一次图片  ->
               
<script>
// 使用uuid模块,生成 uuid
import {v4 as uuid4} from 'uuid'   // 提前安装好uuid模块, cnpm install uuid --save 

export default {
    name: "Register",
    data() {
        return {
            image_code_id: '', // 实际就是uuid
            image_code_url: '', // 图片验证码的地址
        }
    },
    methods: {
        get_img_url(){
            this.uid = uuid4()
            this.image_url = 'http://localhost:8000/users/getimage/?uuid='+uid    
        }
    },
    mounted() {
        // 挂载执行方法,让网页初始加载时,就可以正常显示图片验证码
        this.get_img_url();
    }
}
</script>
3. 图片验证码认证
django
  • 接收前端发送的参数:image_code_id和 用户输入的验证码
  • 取出redis中的 验证码
  • 如果取不到,说明过期,返回对应的错误信息即可
  • 如果取到验证码,进行对比,注意: 统一大小写
4.短信验证
容联云

由于容联云也是采用Restful接口进行功能实现,那么发送短信需要模拟请求接口,需要使用python中的requests模块

pip install requests
SDK发送
  • 安装sdk
pip install ronglian_sms_sdk
  • 官方接口调用方式
from ronglian_sms_sdk import SmsSDK

accId = '8a216da878005a800178a251439d39da'
accToken = 'dc4fd2e2a23e45a68474dbc6d1233eda'
appId = '8a216da878005a800178a251449839e1'

import json
def send_message(mobile,code,time):
    sdk = SmsSDK(accId, accToken, appId)
    tid = '1'
    datas = (code, time)
    resp = sdk.sendMessage(tid, mobile, datas)
    result = json.loads(resp)
    if result['statusCode'] == '000000':
        return 1
    return 2

发送短信验证码,验证图片验证码

#发送短信验证码
import random
class SendMes(APIView):
    def get(self,request):
        #接收客户端发送的数据
        imagecode = request.GET.get('imagecode')
        mobile = request.GET.get('mobile')
        uuid = request.GET.get('uuid')
        if not all([imagecode,mobile]):
            return Response({'code':10017})
        #验证图片验证码
        conn = get_redis_conn()
        #redis中取验证码
        code = conn.get(uuid)
       
        if code:
            code = str(code,encoding='utf8')
            #图片验证码对比
            if imagecode.lower() == code.lower():
                #验证通过后调用发送短信接口
                sms_code = random.randint(10000,99999)
                result = send_message(mobile,sms_code,1)
                #假如短信验证码发送成功
                if result:
                    #redis存短信验证码
                    conn.setex(mobile,60,sms_code)
                    #把图片验证码从redis删除
                    conn.delete(uuid)
                    return Response({'code':200})
                else:
                    return Response({'code':10020})
            else:
                return Response({'code':10019})
        else:
            return Response({'code':10018})


vue页面

//获取短信验证码
		getMsgCode(){
			//获取用户输入的图片验证码
			var imagecode = this.picCode
			var mobile = this.form.mobile
			this.axios.get('users/sendMes/?imagecode='+imagecode+'&mobile='+mobile+'&uuid='+this.imageuuid).then(res=>{
				console.log(res)
			})
		}
5. 用户注册
校验密码
Vue
  • 用户输入密码之后,触发失焦事件
    • 在方法中,使用正则校验密码
  • 用户输入 确认密码之后,触发失焦事件
    • 在方法中,确认密码和密码必须一致
<li>
    <label>密码:</label>
    <input type="password" name="pwd" id="pwd" v-model="pwd" @blur="check_pwd">
    <span class="error_tip" v-show="pwd_flag">请输入8-20位的密码</span>
</li>
<li>
    <label>确认密码:</label>
    <input type="password" name="cpwd" id="cpwd" v-model="pwd2" @blur="check_pwd2">
    <span class="error_tip" v-show="pwd2_flag">两次输入的密码不一致</span>
</li>

<script>
export default {
    name: "Register",
    data() {
        return {
            pwd: '', // 密码
            pwd_flag: false,
            pwd2: '', //确认密码
            pwd2_flag: false
        }
    },
    methods: {
        //  校验密码
        check_pwd() {
            let reg = /^.{8,20}$/

            if (reg.test(this.pwd) === false) {
                this.pwd_flag = true
            } else {
                this.pwd_flag = false
            }
        },
        //  校验确认密码
        check_pwd2() {

            if (this.pwd === this.pwd2) {
                this.pwd2_flag = false
            } else {
                this.pwd2_flag = true
            }
        }
    }
}
</script>

用户注册
django
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *


class RegisterAPIView(APIView):
    def post(self, request):
        # 1. 获取参数
        username = request.data.get('username')
        pwd = request.data.get('pwd')
        pwd2 = request.data.get('pwd2')
        mobile = request.data.get('mobile')
        flag = request.data.get('flag')

        # 2. 校验参数
        if not all([username, pwd, pwd2, mobile, flag]):
            return Response({'msg': '缺少必要参数'}, status=400)
        if pwd != pwd2:
            return Response({'msg': '密码不一致'}, status=400)

        # if flag == 'false':
        #     return Response({'msg': '必须同意注册协议'}, status=400)

        # 3. 保存入库
        try:
            User.objects.create_user(username=username, password=pwd, mobile=mobile)
        except Exception as e:
            return Response({'msg': '注册失败'}, status=500)
        # 4. 返回结果
        return Response({'msg': '注册成功'}, status=201)
Vue页面功能实现
<li class="reg_sub">
    <input type="submit" value="注 册" @click.prevent="register">
</li>

<script>
export default {
    name: "Register",
	...
    methods: {
        // 注册方法
        register() {
            //  校验用户名、密码、确认密码、手机号、图片验证码、是否同意
            this.check_username();
            this.check_pwd();
            this.check_pwd2();
            this.check_mobile();
            this.check_image_code();
            this.check_flag();

            // 任何一个参数有问题,都不能注册
            if (this.username_flag || this.pwd_flag || this.pwd2_flag || this.mobile_flag || this.image_code_flag || this.flag_flag) {
                return
            }

            // 构建表单参数
            let userinfo = new FormData();

            userinfo.append('username', this.username);
            userinfo.append('pwd', this.pwd);
            userinfo.append('pwd2', this.pwd2);
            userinfo.append('mobile', this.mobile);
            userinfo.append('flag', this.flag);

            this.$axios.post('register/', userinfo)
                .then(resp => {
                    console.log(resp.data)
                })
                .catch(err => {
                    console.log(err.response.data)
                })
        }
    }
}
</script>
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楼下安同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值