BBS论坛(十三)

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:;
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:;
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

alidayu = AlidayuAPI()

(3)config.py

ALIDAYU_APP_KEY = 'LTxxxxxxBBfT8Q'
ALIDAYU_APP_SECRET = 'SRxxxxxx8IL8LhJ'
ALIDAYU_SIGN_NAME = '仙剑论坛网站'
ALIDAYU_TEMPLATE_CODE = 'SMS_136xxx947'

(4)perfect_bbs.py

alidayu.init_app(app)

(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();
//使用js的正则判断手机号码,如果不合法,弹出提示框,直接return回去
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();
//使用js的正则判断手机号码,如果不合法,弹出提示框,直接return回去
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
13.1点击更换图形验证码
13.2.短信验证码
13.3.短信验证码加密
13.4.验证码缓存


13-----BBS论坛的更多相关文章

  1. Python之路,Day17 - 分分钟做个BBS论坛

    Python之路,Day17 - 分分钟做个BBS论坛   本节内容: 项目:开发一个简单的BBS论坛 需求: 整体参考"抽屉新热榜" + "虎嗅网" 实现不同 ...

  2. LNMP环境搭建BBS论坛及伪静态

    我们在mysql备份 LNMP环境中的数据库迁移为独立的服务器的基础上搭建BBS论坛:  [root@bqh-117 ~]# mysql -uroot -p123456 Welcome to the ...

  3. Python之路【第十八篇】Django小项目简单BBS论坛部分内容知识点

    开发一个简单的BBS论坛 项目需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可被 ...

  4. python 学习笔记二十 django项目bbs论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  5. python第一百三十天 ---简单的BBS论坛

    简单的BBS论坛 实现功能 git仓库地址:https://github.com/uge3/BBS 1.整体参考“抽屉新热榜” + “博客园” 2.实现不同论坛版块 3.帖子列表展示 4.个人博客主页 ...

  6. Django小项目简单BBS论坛

    开发一个简单的BBS论坛 项目需求: 1 整体参考"抽屉新热榜" + "虎嗅网" 2 实现不同论坛版块 3 帖子列表展示 4 帖子评论数.点赞数展示 5 在线用 ...

  7. Python开发一个简单的BBS论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  8. bbs论坛浏览器兼容性问题

    一直都是在chrome上进行调试,今天终于把bbs论坛这个项目搭建完了,进入IE.Firefox看了看 吓哭了!!! 火狐 Edge chrome 特别是加了<!DOCTYPE html> ...

  9. 开源BBS论坛软件推荐

    七款开源BBS论坛软件推荐(1) 本文介绍了七个开源的BBS论坛软件(在英文界一般叫做Forum).可能国内的朋友们比较熟悉Discuz!和PHPwind,但其实我们的选择还是很多的,而且下面介绍的这 ...

  10. Django项目 BBS论坛

    BBS论坛 一.项目表分析 二.自定义form组件 三.注册功能 四.BBS论坛 登录功能

随机推荐

  1. bzoj1735 [Usaco2005 jan]Muddy Fields 泥泞的牧场

    传送门 分析 我们知道对于没有障碍的情况就是将横轴点于纵轴点连边 于是对于这种有障碍的情况我们还是分横轴纵轴考虑 只不过对于有障碍的一整条分为若干个无障碍小段来处理 然后将标号小段连边,跑最大匹配即可 ...

  2. 100722E The Bookcase

    传送门 题目大意 给你一些书的高度和宽度,有一个一列三行书柜,要求放进去书后,三行书柜的高的和乘以书柜的宽度最小.问这个值最小是多少. 分析 我们可以先将所有书按照高度降序排好,这样对于每一层只要放过 ...

  3. Luogu 1314 [NOIP2011] 聪明的质监员

    二分答案 + 前缀和. 题面中式子的意思是每一个区间$[l, r]$的贡献是这个区间内$w_i \geq W$的个数乘以这些$i$的$v_i$和. 很快发现了答案具有单调性,可以做两遍二分,分别看看小 ...

  4. 前端(HTML/CSS/JS)-CSS编码规范

    1. 文件名规范 文件名建议用小写字母加中横线的方式.为什么呢?因为这样可读性比较强,看起来比较清爽 https://stackoverflow.com/questions/25704650/disa ...

  5. Java Calendar 类的时间操作.RP

    JavaCalendar 类时间操作,这也许是创建和管理日历最简单的一个方案,示范代码很简单. 演示了获取时间,日期时间的累加和累减,以及比较. 原文地址:blog.csdn.NET/joyous/a ...

  6. Website开发前页面设计 Mockup的一些工具

    这里介绍的Website开发前,页面设计的一些工具 1. Balsamiq    (我们公司用的) https://balsamiq.com/download/ 2. Figma https://ww ...

  7. [译]Javascript substring实例

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  8. ubuntu基础知识与技巧

    root用户与超级用户的切换 (1)  sudo -i (2)  sudo su (3)  su root 安装升级 查看软件xxx安装内容 dpkg -L xxx 查找软件库中的软件 apt-cac ...

  9. [转]ORA-12516, TNS:listener could not find available handler with matching protocol stack

    转至:http://blog.csdn.net/MichaelSrc/article/details/6760247 1.查看当前连接进程数 SQL>select count(*) from v ...

  10. c#设计模式-单例模式【转】

    单例模式三种写法: 第一种最简单,但没有考虑线程安全,在多线程时可能会出问题 public class Singleton { private static Singleton _instance = ...