• vue+drf+第三方滑动验证码的接入实现


    1、背景

    近期在项目开发练习中用到了登录功能 + 验证码的需求,验证码一般分为三种类型:图片验证码、短信验证码、滑动验证码,相关实现思路如下

    • 图片验证码

    对于图片验证码的实现可以借助python中的第三方模块pillow的相关方法进行实现(有时间会写文章)

    • 短信验证码

    短信验证码的主要思路是通过调用第三方短信接口向手机发送短信,接收用户输入并与系统生成的随机数串比对

    • 滑动验证码

    滑动验证码一般是利用第三方的验证码服务提供商,例如腾讯防水墙极验验证等。和我们自己实现验证码的思路相比较,第三方验证码更为安全可靠

    本文以腾讯防水墙为例,记录在vuedrf组合的前后端分离项目中接入第三方滑动验证码服务

    2、验证流程

    验证的前后端调用时序图如下(图片来源于腾讯验证码官方文档)

    3、创建验证

    首先登陆到腾讯云控制台创建一个云 API 密钥,在左侧导航栏选择【访问管理】>【API 密钥管理】,进入 API 密钥管理页面,单击【新建密钥】创建密钥。

    然后进入验证码控制台,单击【新建验证】,根据需求输入验证名称、验证所属域名、验证渠道(Web 端或小程序插件)及验证场景,填写完成后,单击【确定】完成验证创建。

    领取免费包,单击【领取免费包】,即可完成免费包(20000次验证)领取。

    最后,查看申请到的资源信息

    4、前端代码

    4.1 添加核心js文件

    把防水墙的前端核心js文件在项目根目录下index.html中使用script标签引入

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
        <title>opsweb</title>
      </head>
      <body>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    

    或者在src/main.js中通过import引入,导入前需要将上面的核心js文件下载到项目静态文件目录中

    // 导入防水墙验证码的核心js文件
    import "../static/js/TCaptcha";
    

    4.2 添加配置

    src/settings.js中添加配置

    export default {
      HOST: 'http://opsapi.ssgeek.com:8000',  // 后端api地址
      TC_captcha:{
        app_id: "2020427221",  // 腾讯防水墙APPID配置
      },
    }
    

    4.3 组件修改

    修改登录页面vue组件Login.vue,将登录按钮绑定到验证码显示的自定义方法上,先触发验证码请求再触发登录

    template部分

    <template>
    <!--登录内容开始-->
    <div class="inp" v-if="login_type==0">
      <input v-model="username" type="text" placeholder="用户名" class="user">
      <input v-model="password" type="password" name="" class="pwd" placeholder="密码">
      <div class="rember">
        <p>
          <input v-model="remember_me" type="checkbox" class="no" name="a"/>
          <span>记住密码</span>
        </p>
      </div>
      <button class="login_btn" @click="show_captcha">登录</button>
    <!--登录内容结束-->
    </div>
    </template>
    

    script部分

    <script>
    export default {
      name: 'Login',
      data() {
        return {
          login_type: 0,
          remember_me: false,
          username: "",
          password: "",
        }
      },
      methods: {
        show_captcha() {
          var captcha1 = new TencentCaptcha(this.$settings.TC_captcha.app_id, res=> {
            /*
            res:
            appid: "2020427221"  # 验证码的APPID
            randstr: "@GCV"      # 随机字符串,防止重复
            ret: 0               # 0表示用户操作成功,2表示用户主动关闭验证码窗口
            ticket: ""           # 验证通过以后的票据,提供给后端,将来到验证码服务器中进行
            */
            // console.log(res);
            this.$axios.get(`${this.$settings.HOST}/users/captcha/`,{
              params:{
                ticket: res.ticket,
                randstr: res.randstr,
              }
            }).then(response=>{
              if(response.data.detail){
                // 继续进行登录处理
                this.login();
              }
            }).catch(error=>{
              this.$message.error("对不起,验证码校验不通过!");
            });
          });
          captcha1.show();
        },
        login() {
          // 判断用户是否输入用户名或密码,否则提示用户输入
          if (!this.username) {
            this.$message.error('请输入用户名!')
          } else if (!this.password) {
            this.$message.error('请输入密码!')
          } else {
            // 携带用户名和密码,提交post请求
            this.$axios.post(`${this.$settings.HOST}/users/login/`, {
              username: this.username,
              password: this.password,
            }).then((res) => {
              // 存储token
              if (this.remember_me) {
                localStorage.token = res.data.token;
                sessionStorage.removeItem('token')
              } else {
                sessionStorage.token = res.data.token;
                localStorage.removeItem('token')
              }
              // 跳转到首页
              this.$router.push('/hippo/showcenter')
            }).catch((error) => {  // 捕获请求返回的错误,4xx,5xx
              this.$message.error('用户名或者密码有误,请重新输入!')
            })
          }
        },
      },
    };
    

    5、后端代码

    相关操作指引可以参考官方示例:https://007.qq.com/python-access.html

    5.1 添加配置

    将腾讯验证码控制台查看到的验证信息配置到drf后端代码的配置文件中

    # 腾讯防水墙配置
    TENCENT_CAPTCHA = {
        "GATEWAY": "https://ssl.captcha.qq.com/ticket/verify",  # 验证码验证地址
        "APPID": "2020427221",  # 验证码应用的APPID
        "App_Secret_Key": "0mnAr1EpNTjm63fQgKPU87w**",  # 验证码应用的AppSecretKey
    }
    

    5.2 接收验证并返回

    在用户app下编写用户验证码的普通类视图view

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    from django.conf import settings
    from urllib.parse import urlencode
    from urllib.request import urlopen
    import json
    import ssl
    
    
    # Create your views here.
    class CaptchaAPIView(APIView):
        """验证码"""
        ssl._create_default_https_context = ssl._create_unverified_context
    
        def get(self, request):
            """接收客户端提交的验证码相关信息"""
            params = {
                "aid": settings.TENCENT_CAPTCHA.get("APPID"),
                "AppSecretKey": settings.TENCENT_CAPTCHA.get("App_Secret_Key"),
                "Ticket": request.query_params.get("ticket"),
                "Randstr": request.query_params.get("randstr"),
                "UserIP": request._request.META.get("REMOTE_ADDR")
            }
            # 把字典数据转换成地址栏的查询字符串格式
            # aid=xxx&AppSecretKey=xxx&xxxxx
            params = urlencode(params)
            # print(params)
            url = settings.TENCENT_CAPTCHA.get("GATEWAY")
            # 发送http的get请求
            f = urlopen("%s?%s" % (url, params))
            # https://ssl.captcha.qq.com/ticket/verify?aid=xxx&AppSecretKey=xxx&xxxxx
            # f.read() 读取响应信息
            content = f.read()
            res = json.loads(content)
            # print(res)
            if int(res.get("response")) == 1:
                # 验证成功
                return Response({"detail": 1})
            else:
                # 验证失败
                return Response({"detail": 0}, status=status.HTTP_400_BAD_REQUEST)
    

    5.3 添加url路由

    最后,添加用于前端发送请求的后端url路由

    from django.urls import path
    from rest_framework_jwt.views import obtain_jwt_token
    from . import views
    
    urlpatterns = [
        path('login/', obtain_jwt_token),
        path('captcha/', views.CaptchaAPIView.as_view()),  # 验证码校验
    ]
    

    6、运行测试

    最终效果如下

    在腾讯验证码的后台可以看到详细的请求信息图表

    参考:https://cloud.tencent.com/document/product/1110/

  • 相关阅读:
    批量修改文件名
    查看数据库版本及当前登录用户是什么?
    安装mysql5.5时候的报错解决办法:
    mysql.sock的作用
    Linux系统编程15_C函数总结
    Linux系统编程14_信号和进程状态
    Linux系统编程13_CoreDump
    Linux系统编程12_标准库和POSIX标准头文件
    gcc使用
    http长链接短链接
  • 原文地址:https://www.cnblogs.com/ssgeek/p/14358002.html
Copyright © 2020-2023  润新知