13.1点击更换图形验证码
(1)front/signup.html
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="graph_captcha" placeholder="图形验证码">
<span class="input-group-addon captcha-addon">
<img id="captcha-img" class="captcha-img" src="{{ url_for('front.graph_captcha') }}" alt="">
</span>
</div>
</div>
(2)static/front/css/signup.css
.sign-box {
width: 300px;
margin: 0 auto;
padding-top: 50px;
}
.captcha-addon {
padding: 0;
overflow: hidden;
}
.captcha-img {
width: 94px;
height: 32px;
cursor: pointer;
}
body {
background: #f3f3f3;
}
.outer-box {
width: 854px;
background: #fff;
margin: 0 auto;
overflow: hidden;
}
.logo-box {
text-align: center;
padding-top: 40px;
}
.logo-box img {
width: 60px;
height: 60px;
}
.page-title {
text-align: center;
}
.sign-box {
width: 300px;
margin: 0 auto;
padding-top: 50px;
}
.captcha-addon {
padding: 0;
overflow: hidden;
}
.captcha-img {
width: 94px;
height: 32px;
cursor: pointer;
}
(3)static/common/zlparam.js
var zlparam = {
setParam: function (href,key,value) {
var isReplaced = false;
var urlArray = href.split('?');
if(urlArray.length > 1){
var queryArray = urlArray[1].split('&');
for(var i=0; i < queryArray.length; i++){
var paramsArray = queryArray[i].split('=');
if(paramsArray[0] == key){
paramsArray[1] = value;
queryArray[i] = paramsArray.join('=');
isReplaced = true;
break;
}
}
if(!isReplaced){
var params = {};
params[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(params);
}else{
href = href + '?' + $.param(params);
}
}else{
var params = queryArray.join('&');
urlArray[1] = params;
href = urlArray.join('?');
}
}else{
var param = {};
param[key] = value;
if(urlArray.length > 1){
href = href + '&' + $.param(param);
}else{
href = href + '?' + $.param(param);
}
}
return href;
}
};
(4)static/front/js/signup.js
$(function () {
$('#captcha-img').click(function (event) {
var self= $(this);
var src = self.attr('src');
var newsrc = zlparam.setParam(src,'xx',Math.random());
self.attr('src',newsrc);
});
});
(5)front/signup.html中引用js和css
<script src="{{ static('common/zlparam.js') }}"></script>
<script src="{{ static('front/js/front_signup.js') }}"></script>
<link rel="stylesheet" href="{{ static('front/css/front_signup.css') }}">
现在点击验证码,就可以更换验证码了。
13.2.短信验证码
(1)utils/alidayu.py
# 仙剑论坛-阿里大于短信验证码sdk
import hashlib
from time import time
import logging
import requests
class AlidayuAPI(object):
APP_KEY_FIELD = 'ALIDAYU_APP_KEY'
APP_SECRET_FIELD = 'ALIDAYU_APP_SECRET'
SMS_SIGN_NAME_FIELD = 'ALIDAYU_SIGN_NAME'
SMS_TEMPLATE_CODE_FIELD = 'ALIDAYU_TEMPLATE_CODE'
def __init__(self, app=None):
self.url = 'https://eco.taobao.com/router/rest'
self.headers = {
'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
"Cache-Control": "no-cache",
"Connection": "Keep-Alive",
}
if app:
self.init_app(app)
def init_app(self,app):
config = app.config
try:
self.key = config[self.APP_KEY_FIELD]
self.secret = config[self.APP_SECRET_FIELD]
self.sign_name = config[self.SMS_SIGN_NAME_FIELD]
self.api_params = {
'sms_free_sign_name': config[self.SMS_SIGN_NAME_FIELD],
'sms_template_code': config[self.SMS_TEMPLATE_CODE_FIELD],
'extend': '',
'sms_type': "normal",
"method": "alibaba.aliqin.fc.sms.num.send",
"app_key": self.key,
"format": "json",
"v": "2.0",
"partner_id": "",
"sign_method": "md5",
}
except Exception as e:
logging.error(e.args)
raise ValueError('请填写正确的阿里大鱼配置!')
def send_sms(self,telephone,**params):
self.api_params['timestamp'] = str(int(time() * 1000))
self.api_params['sms_param'] = str(params)
self.api_params['rec_num'] = telephone
newparams = "".join(["%s%s" % (k, v) for k, v in sorted(self.api_params.items())])
newparams = self.secret + newparams + self.secret
sign = hashlib.md5(newparams.encode("utf-8")).hexdigest().upper()
self.api_params['sign'] = sign
resp = requests.post(self.url,params=self.api_params,headers=self.headers)
data = resp.json()
try:
result = data['alibaba_aliqin_fc_sms_num_send_response']['result']['success']
return result
except:
print('='*10)
print("阿里大于错误信息:",data)
print('='*10)
return False
(2)exts.py
(3)config.py
ALIDAYU_APP_KEY = 'LTxxxxxxBBfT8Q'
ALIDAYU_APP_SECRET = 'SRxxxxxx8IL8LhJ'
ALIDAYU_SIGN_NAME = '仙剑论坛网站'
ALIDAYU_TEMPLATE_CODE = 'SMS_136xxx947'
(4)perfect_bbs.py
(5)common/views.py
# common/views.py
__author__ = 'derek'
from flask import Blueprint,request
from exts import alidayu
from utils import restful
from utils.captcha import Captcha
bp = Blueprint("common",__name__,url_prefix='/c')
@bp.route('/sms_captcha/')
def sms_captcha():
telephone = request.args.get('telephone')
if not telephone:
return restful.params_error(message='请输入手机号码')
#生成四位数的验证码
captcha = Captcha.gene_text(number=4)
if alidayu.send_sms(telephone,code=captcha):
return restful.success()
else:
# return restful.params_error(message='短信验证码发送失败!')
return restful.success()
(6)signup.html
<script src="{{ static('common/zlajax.js') }}"></script>
<link rel="stylesheet" href="{{ static("common/sweetalert/sweetalert.css") }}">
<script src="{{ static("common/sweetalert/sweetalert.min.js") }}"></script>
<script src="{{ static("common/sweetalert/zlalert.js") }}"></script>
<script src="{{ static('common/zlparam.js') }}"></script>
<script src="{{ static('front/js/front_signup.js') }}"></script>
<link rel="stylesheet" href="{{ static('front/css/front_signup.css') }}">
(7)front_signup.js
$(function () {
$("#sms-captcha-btn").click(function (event) {
event.preventDefault();
var self = $(this);
var telephone = $("input[name='telephone']").val();
if (!(/^1[3578]\d{9}$/.test(telephone))) {
zlalert.alertInfoToast('请输入正确的手机号');
return;
}
zlajax.get({
'url': '/c/sms_captcha?telephone='+telephone,
'success': function (data) {
if(data['code'] == 200){
zlalert.alertSuccessToast('短信验证码发送成功');
self.attr("disabled",'disabled');
var timeCount = 60;
var timer = setInterval(function () {
timeCount--;
self.text(timeCount);
if(timeCount <= 0){
self.removeAttr('disabled');
clearInterval(timer);
self.text('发送验证码');
}
},1000);
}else{
zlalert.alertInfoToast(data['message']);
}
}
});
});
});
13.3.短信验证码加密
(1)common/forms.py
from apps.forms import BaseForm
from wtforms import StringField
from wtforms.validators import regexp,InputRequired
import hashlib
class SMSCaptchaForm(BaseForm):
salt='dfurtn5hdsesjc*&^nd'
telephone=StringField(validators=[regexp(r'1[3578]\d{9}')])
timestamp=StringField(validators=[regexp(r'\d{13}')])
sign=StringField(validators=[InputRequired()])
def validate(self):
result=super(SMSCaptchaForm, self).validate()
if not result:
return False
telephone=self.telephone.data
timestamp=self.timestamp.data
sign=self.sign.data
sign2=hashlib.md5((timestamp+telephone+self.salt).encode('utf-8')).hexdigest()
if sign==sign2:
return True
else:
return False
(2)front/views.py
# common/views.py
__author__ = 'derek'
from flask import Blueprint,request
from exts import alidayu
from utils import restful
from utils.captcha import Captcha
from .form import SMSCaptchaForm
bp = Blueprint("common",__name__,url_prefix='/c')
# @bp.route('/sms_captcha/')
# def sms_captcha():
# telephone = request.args.get('telephone')
# if not telephone:
# return restful.params_error(message='请输入手机号码')
# #生成四位数的验证码
# captcha = Captcha.gene_text(number=4)
# if alidayu.send_sms(telephone,code=captcha):
# return restful.success()
# else:
# # return restful.params_error(message='短信验证码发送失败!')
# return restful.success()
@bp.route('/sms_captcha/',methods=['POST'])
def sms_captcha():
# telephone+timestamp+salt
form=SMSCaptchaForm(request.form)
if form.validate():
telephone=form.telephone.data
captcha=Captcha.gene_text(number=4)
if alidayu.send_sms(telephone,code=captcha):
return restful.success()
else:
# return restful.paramas_error(message='参数错误')
return restful.success()
else:
return restful.params_error(message='参数错误')
(3)front_signup.js
$(function () {
$("#sms-captcha-btn").click(function (event) {
event.preventDefault();
var self = $(this);
var telephone = $("input[name='telephone']").val();
if (!(/^1[3578]\d{9}$/.test(telephone))) {
zlalert.alertInfoToast('请输入正确的手机号');
return;
}
var timestamp = (new Date).getTime();
var sign = md5(timestamp + telephone + 'dfurtn5hdsesjc*&^nd');
zlajax.post({
'url': '/c/sms_captcha/',
'data': {
'telephone': telephone,
'timestamp': timestamp,
'sign': sign
},
'success': function (data) {
if (data['code'] == 200) {
zlalert.alertSuccessToast('短信验证码发送成功');
self.attr("disabled", 'disabled');
var timeCount = 60;
var timer = setInterval(function () {
timeCount--;
self.text(timeCount);
if (timeCount <= 0) {
self.removeAttr('disabled');
clearInterval(timer);
self.text('发送验证码');
}
}, 1000);
} else {
zlalert.alertInfoToast(data['message']);
}
}
});
});
});
(4)front/signup.html
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
13.4.验证码缓存
把front/views里面的图形验证码放到common/views.py下面
common/views.py
# common/views.py
__author__ = 'derek'
from flask import Blueprint, request,make_response
from exts import alidayu
from utils import restful, zlcache
from .form import SMSCaptchaForm
from utils.captcha import Captcha
from io import BytesIO
bp = Blueprint("common", __name__, url_prefix='/c')
# @bp.route('/sms_captcha/')
# def sms_captcha():
# telephone = request.args.get('telephone')
# if not telephone:
# return restful.params_error(message='请输入手机号码')
# #生成四位数的验证码
# captcha = Captcha.gene_text(number=4)
# if alidayu.send_sms(telephone,code=captcha):
# return restful.success()
# else:
# # return restful.params_error(message='短信验证码发送失败!')
# return restful.success()
@bp.route('/sms_captcha/', methods=['POST'])
def sms_captcha():
# telephone+timestamp+salt
form = SMSCaptchaForm(request.form)
if form.validate():
telephone = form.telephone.data
captcha = Captcha.gene_text(number=4)
if alidayu.send_sms(telephone, code=captcha):
zlcache.set(telephone, captcha) # 验证码保存到缓存中
return restful.success()
else:
# return restful.paramas_error(message='参数错误')
zlcache.set(telephone, captcha) # 测试用
return restful.success()
else:
return restful.params_error(message='参数错误')
@bp.route('/captcha/')
def graph_captcha():
text,image = Captcha.gene_graph_captcha()
zlcache.set(text.lower(),text.lower())
out = BytesIO()
image.save(out,'png') #指定格式为png
out.seek(0) #把指针指到开始位置
resp = make_response(out.read())
resp.content_type = 'image/png'
return resp
本文由LIKE.TG编辑部转载自互联网并编辑,如有侵权影响,请联系官方客服,将为您妥善处理。
This article is republished from public internet and edited by the LIKE.TG editorial department. If there is any infringement, please contact our official customer service for proper handling.