• 解决reguest.session获取不到指定信息问题(钉钉机器人实现发短信--webhook)


    1 用户模块梳理

    1.1 注册

    我们在编写注册模块的时候,尤其是高负载的情况下,尽可能地不读库,会极大地提高我们的性能。可以采用唯一索引。

    1.2 登录

    在登录的时候,我们要有一个思想,单因子登录,双因子登录和三因子登录

    • 单因子登录:传统的验证用户名,密码这种机制不安全(密码为唯一登录,不安全)图片验证码
    • 双因子登录:需要东西来验证,识别(短信,邮件)
    • 三因子登录:滑块,面部识别,指纹验证

    1.3 webhook

    • 动向扩展

    整体思路就是,通过webhook把验证码发给机器人,机器人在钉钉端告诉用户这个码是多少,用户看到码,把码通过表单形式,然后django端作对比,判断是否登录成功。

    2 所遇到的问题

    2.1 设置钉钉机器人问题

    • 重要的地方(一)---> 加签

    • 重要的地方(二)---> 获取webhook

    2.2 session问题

    • 非常可气,postman调试十分正常,但是浏览器没有效果。

    • 根据自己的理解,写了一个比较low的解决方案。

    • 由于采取的是session存储,那就意味着,没有办法在获取完验证码,request.session['key']=value 的情况下,在下一个视图继续获取了。

    3 代码实例

    3.1 Django端

    • settings里无需配置
    3.1.1 views.py
    from django.contrib.auth.hashers import make_password, check_password
    from django.contrib.sessions.models import Session
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from userapp.models import UserModel
    from userapp.utils import create_token, message_code, dingding_robot
    
    
    class RegisterView(APIView):
    
        def post(self, request):
            username = request.data.get('username')
            password = request.data.get('password')
            tel = request.data.get('tel')
            try:
                user = UserModel.objects.create(username=username, password=make_password(password),tel=tel)
                token = create_token(user)
                return Response(
                    {'msg': '注册成功', 'code':200, 'token': token}
                )
            except Exception as e:
                print('异常', e)
                return Response(
                    {'msg': '用户名或手机号重复', 'code':400}
                )
    
    class LoginView(APIView):
    
        def post(self, request):
            num = request.data.get('num')
            username = request.data.get('username')
            password = request.data.get('password')
            get_key = request.data.get('session_key')
            user = UserModel.objects.filter(username=username).first()
            if check_password(password, user.password):
                session_data = Session.objects.get(pk=get_key).get_decoded()
                num_get = session_data.get('num')
                if num == str(num_get):
                    token = create_token(user)
                    return Response(
                        {'msg': '登录成功', 'code': 200, 'token': token, 'num':num}
                    )
            return Response(
                {'msg': '登录失败', 'code': 400}
            )
    
    
    class DingDingView(APIView):
    
        def get(self, request):
            num = message_code()
            dingding_robot(num)
            request.session['num'] = num
            request.session.set_expiry(300)
            if not request.session.session_key:
                request.session.create()
            return Response(
                {'msg': '发送成功', 'code':200, 'num':num, 'session_key': request.session.session_key}
            )
    
    3.1.2 utils.py
    # -*- coding: utf-8 -*-
    from rest_framework_jwt.settings import api_settings
    def create_token(user):
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token
    
    
    def message_code():
        import random
        num = random.randint(100000, 999999)
        return num
    
    
    def dingding_robot(num):
        import time
        import hmac
        import hashlib
        import base64
        import urllib.parse
        timestamp = str(round(time.time() * 1000))
        secret = 'SECc0cc53c0179ded46f9050ff40c8c767f2bd0f50a2e7255c1bc9afa014d246db2'
        secret_enc = secret.encode('utf-8')
        string_to_sign = '{}
    {}'.format(timestamp, secret)
        string_to_sign_enc = string_to_sign.encode('utf-8')
        hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
        sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
        import requests, json  # 导入依赖库
        headers = {'Content-Type': 'application/json'}  # 定义数据类型
        webhook = 'https://oapi.dingtalk.com/robot/send?access_token=2c3730563856be4f9dfc1ed8cfa1e1789c6ec88ba4964782529d4b866f503d1a&timestamp={}&sign={}'.format(timestamp,sign)
        data = {
            "msgtype": "text",
            "text": {"content": num},
            "isAtAll": True}
        res = requests.post(webhook, data=json.dumps(data), headers=headers)  # 发送post请求
        return res
    

    3.2 Vue端

    3.2.1 Register.vue
    <template>
        <div style="margin-top:200px">
            <center><h1 style="margin-top:50px">注&emsp;册</h1></center>
            <div style="margin:0 auto;500px;height:200px">
                用户名:
                    <a-input placeholder="input your username" style="300px" v-model="username"/>
                <br>
                <br>
                密&ensp;&ensp;码:
                    <a-input-password placeholder="input your password" style="300px" v-model="password"/>
                    <br>
                    <br>
                手机号:
                    <a-input placeholder="input your telphone" style="300px" v-model="tel"/>
                    <br>
                    <br>
                  <a-button type="primary" @click="register">注册</a-button>
            </div>
        </div>
    </template>
    
    <script>
    import { user_register } from '@/http/apis'
    export default {
        data() {
            return {
                username:'',
                password:'',
                tel:''
            }
        },
        methods: {
            register(){
                let register_data = {
                    'username':this.username,
                    'password': this.password,
                    'tel':this.tel
                }
                user_register(register_data).then(res=>{
                    // 已生成token,可以免登陆直接跳主页的,后续写
                    res.code == 200?alert('注册成功,即将跳转登录界面')&this.$router.push('/login'):alert('请保证用户名和手机号唯一哦')
                })
            }
        },
        created() {
    
        }
    }
    </script>
    
    <style scoped>
    
    </style>
    
    3.2.2 Login.vue
    <template>
        <div style="margin-top:200px">
            <center><h1 style="margin-top:50px">登&emsp;录</h1></center>
            <div style="margin:0 auto;500px;height:200px">
                用户名:
                    <a-input placeholder="input your username" style="300px" v-model="username"/>
                <br>
                <br>
                密&ensp;&ensp;码:
                    <a-input-password placeholder="input your password" style="300px" v-model="password"/>
                    <br>
                    <br>
              <p>
                  <a-input type="text" v-model="message_code"  style="200px"/>&emsp;<a-button type="primary"  @click="getMessageCode">钉钉获取验证码</a-button>
              </p>
                  <a-button type="primary" @click="login">登录</a-button>
            </div>
        </div>
    </template>
    
    <script>
    import { get_message_code, user_login } from '@/http/apis'
    export default {
        data() {
            return {
                username:'',
                password:'',
                message_code:'',
            }
        },
        methods: {
            // 获取验证码
            getMessageCode(){
                get_message_code().then(res=>{
                    console.log(res)
                    res.code == 200?alert('获取验证码成功')&sessionStorage.setItem('session_key', res.session_key):alert('失败失败')
                })
            },
            // 登录
            login(){
                let user_info = {
                    'username':this.username,
                    'password':this.password,
                    'num':this.message_code,
                    'session_key': sessionStorage.getItem('session_key')
                }
                user_login(user_info).then(
                    res=>{
                       console.log(res) 
                       res.code == 200?alert('登录成功'):alert('登录失败')
                    }
                )
            }
        },
        created() {
    
        }
    }
    </script>
    
    <style scoped>
    
    </style>
    
  • 相关阅读:
    IOI2000 回文字串
    洛谷 P2758 编辑距离
    NOIP2012普及第三题 摆花
    [SCOI2005]骑士精神
    [USACO1.5]八皇后 Checker Challenge
    Codeforces Round #637 (Div. 2) 题解
    核电站---两种DP解法
    POJ1077 八数码问题
    洛谷 P1162 填涂颜色
    jQuery火箭图标返回顶部代码
  • 原文地址:https://www.cnblogs.com/mapel1594184/p/14145853.html
Copyright © 2020-2023  润新知