解決reguest.session獲取不到指定資訊問題(釘釘機器人實現發簡訊--webhook)
阿新 • • 發佈:2020-12-16
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 = '{}\n{}'.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×tamp={}&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">注 冊</h1></center>
<div style="margin:0 auto;width:500px;height:200px">
使用者名稱:
<a-input placeholder="input your username" style="width:300px" v-model="username"/>
<br>
<br>
密  碼:
<a-input-password placeholder="input your password" style="width:300px" v-model="password"/>
<br>
<br>
手機號:
<a-input placeholder="input your telphone" style="width: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">登 錄</h1></center>
<div style="margin:0 auto;width:500px;height:200px">
使用者名稱:
<a-input placeholder="input your username" style="width:300px" v-model="username"/>
<br>
<br>
密  碼:
<a-input-password placeholder="input your password" style="width:300px" v-model="password"/>
<br>
<br>
<p>
<a-input type="text" v-model="message_code" style="width:200px"/> <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>