一、验证码
1.注册蓝图
-
在info/modules文件夹下新建一个名字为passport的python文件夹,再在这个文件夹下新建一个views.py文件
- 打开passport/init.py文件
from flask import Blueprint
passport_blu = Blueprint("passport", __name__,url_prefix='/passport')
from . import views
- 打开info/init.py文件
from info.modules.passport import passport_blu
app.register_blueprint(passport_blu)
2.编写验证码
- 打开static/news/js/mian.js(大概153行左右)
var imageCodeId = ""
var preimageCodeId = ""
// TODO 生成一个图片验证码的编号,并设置页面中图片验证码img标签的src属性
function generateImageCode() {
//生成一个随机字符串
imageCodeId = generateUUID();
//验证码图片地址
image_url = '/passport/image_code?cur_id = '+imageCodeId+'&pre_id='+preimageCodeId
//将image_url设置到image标签的src属性中
$('.get_pic_code').attr('src',image_url)
//
preimageCodeId = imageCodeId
}
验证码字体文件包链接:https://pan.baidu.com/s/1ZDpaQEQw5DZ2mbZ9a5YS7w
提取码:2mlx
- 在这个info文件夹下新建一个名为utils的文件夹,将上面的文件夹放入其中
- 这个字体记得导入到电脑字体库中,其目录为:C:\Windows\Fonts
- 安装pillow
pip install pillow
response_code.py文件链接:https://pan.baidu.com/s/1vtCIxBNVG4s2nt0pCvhEBg
提取码:fr5v
-
将上面这个文件放入到刚刚utils文件夹内
- 打开info/modules/passport/views.py文件
#功能描述: 图片验证码
#请求地址: /passport/image_code
#请求方式: GET
#请求参数: 随机字符串(uuid)cur_id, 上一个字符串:pre_id
#返回值: 返回图片
from flask import jsonify, make_response, current_app, request
from info import redis_store, constants
from info.modules.passport import passport_blu
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
@passport_blu.route('/image_code')
def get_image_code():
"""
思路分析:
1.获取参数
2.校验参数
3.生成图片验证码
4.保存到redis
5.返回
:return:
"""
#1.获取参数
cur_id = request.args.get('cur_id')
pre_id = request.args.get('pre_id')
#2.校验参数
if not cur_id:
return jsonify(errno=RET.PARAMERR,errmsg='参数不全')
#3.生成图片验证码
try:
name,text,image_data = captcha.generate_captcha()
#4.保存到redis
#参数1:保存到redis的key
#参数2:图片验证码
#参数3:过期时间
redis_store.set('image_code:%s'%cur_id,text,constants.IMAGE_CODE_REDIS_EXPIRES)
#判断有没有上个编号
if pre_id:
redis_store.delete('image_code:%s'%pre_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="验证操作失败")
#5.返回图片验证码
response = make_response(image_data)
response.headers["Content-Type"] = 'image/jpg'
return response
-
刷新页面
验证码出来了
-
打开redis数据库
数据库里面会出现验证码
二、短信验证
1.云通讯注册
- 我们短信验证功能会使用第三方平台,也就是云通讯
-
注册账号
云通讯包链接:https://pan.baidu.com/s/1iS9zc54G759NLnJg5N-37Q
提取码:4idv
-
在info文件夹下新建一个libs文件夹,将刚刚的链接里面的文件夹放入libs中
-
打开sms.py文件
将这三个数值进行一一对应
- 运行程序
在运行程序的时候我这边出现了一个问题,出现{'172001':'网络错误'}
我的解决办法是放入了两行代码:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context # 全局取消证书验证
# 说明:请求地址,生产环境配置成cloopen.com
_serverIP = 'app.cloopen.com'
再次运行的话就会好使了
- 打开passport/views.py文件
#功能描述: 发送短信
# 请求路径: /passport/sms_code
# 请求方式: POST
# 请求参数: mobile, image_code,image_code_id
# 返回值: errno, errmsg
@passport_blu.route('/sms_code',methods=['POST'])
def get_sms_code():
"""
思路分析:
1.获取参数
2.校验参数,为空检验,格式校验
3.取出redis中的图片验证码
4.判断是否过期
5.删除redis中图片验证码
6.正确性判断
7.生成短信验证码
8.发送短信
9.判断是否发送成功
10.保存短信验证码到redis
11.返回响应
"""
# 1.获取参数
json_data = request.data
dict_data = json.loads(json_data)
mobile = dict_data.get('mobile')
image_code = dict_data.get('image_code')
image_code_id = dict_data.get('image_code_id')
# 2.校验参数,为空检验,格式校验
if not all([mobile,image_code,image_code_id]):
return jsonify(errno=RET.PARAMERR,errmsg="参数不全")
if not re.match('1[35789]\d{9}',mobile):
return jsonify(errno=RET.DATAERR,errmsg="手机号格式不正确")
# 3.取出redis中的图片验证码
try:
redis_image_code = redis_store.get('image_code:%s'%image_code_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="数据获取失败")
# 4.判断是否过期
if not redis_image_code:
return jsonify(errno=RET.NODATA,errmsg="图片验证码过期")
# 5.删除redis中图片验证码
try:
redis_store.delete('image_code:%s'%image_code_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="获取失败")
# 6.正确性判断
if image_code.upper() != redis_image_code.upper():
return jsonify(errno=RET.DATAERR,errmsg="图片验证码错误")
# # 7.生成短信验证码
sms_code = '%06d'%random.randint(0,999999)
current_app.logger.debug('短信验证码 = %s'%sms_code )
# 8.发送短信
try:
ccp = CCP()
result = ccp.send_template_sms(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],1)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.THIRDERR,errmsg="云通讯发送失败")
# 9.判断是否发送成功
if result == -1:
return jsonify(errno=RET.DATAERR,errmsg="发送短信失败")
# 10.保存短信验证码到redis
try:
redis_store.set('sms_code:%s'%mobile,sms_code,constants.SMS_CODE_REDIS_EXPIRES)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="短信保存失败")
# 11.返回响应
return jsonify(errno=RET.OK,errmsg="发送成功")
- 打开info/static/news/js/main.js文件
// TODO 发送短信验证码
//拼接参数
var params = {
"mobile": mobile,
"image_code": imageCode,
"image_code_id": imageCodeId
}
//发送获取短信请求
$.ajax({
url: '/passport/sms_code',//请求地址
type: 'post',
data: JSON.stringify(params),
contentType: 'application/json',
headers: {'X-CSRFToken': getCookie('csrf_token')},
success: function (resp) {
//判断是否请求成功
if (resp.errno == '0') {
//定义倒计时时间
var num = 60;
//创建定时器
var t = setInterval(function () {
//判断是否倒计时结束
if (num == 1) {
//清除定时器
clearInterval(t)
//设置标签点击事件,并设置内容
$(".get_code").attr("onclick", 'sendSMSCode()');
$(".get_code").html('点击获取验证码');
} else {
//设置秒数
num -= 1;
$('.get_code').html(num + '秒');
}
}, 1000);//一秒走一次
} else {//发送失败
alert(resp.errmsg);
// 重新设置点击事件,更新图片验证码
$(".get_code").attr("onclick", 'sendSMSCode()');
generateImageCode();
}
}
})
}
-
运行程序
手机上也收到了短信验证码
三、注册与登录
- 打开passport/views.py文件
# 登录
@passport_blu.route('/login', methods=['POST'])
def login():
# 1.获取参数
# 2.校验
# 3.通过手机号获取对象
# 4. 判断用户是否存在
# 5.判断密码
# 6. 保存用户信息到session中
# 7. 返回响应
# 1.获取参数
mobile = request.json.get('mobile')
password = request.json.get('password')
# 2.校验
if not all([mobile, password]):
return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
if not re.match('1[35789]\d{9}',mobile):
return jsonify(errno=RET.DATAERR,errmsg="手机号格式不正确")
# 3.通过手机号获取对象
try:
user = User.query.filter(User.mobile == mobile).first()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="查询用户异常")
# 4. 判断用户是否存在
if not user:
return jsonify(errno=RET.NODATA,errmsg="该用户未注册")
# 5.判断密码
# if not user.check_passowrd(password):
if user.password_hash != password:
return jsonify(errno=RET.DATAERR,errmsg="密码错误")
# 6. 保存用户信息到session中
session['user_id'] = user.id
session['mobile'] = user.mobile
session['nick_name'] = user.nick_name
user.last_login = datetime.now()
# 7. 返回响应
current_app.logger.debug('登录成功')
return jsonify(errno=RET.OK, errmsg="登录成功")
# 注册功能的实现
@passport_blu.route('/register', methods=['POST'])
def register():
"""
1. 获取参数
2.校验参数
3. 通过手机号取出验证码
4. 判断短信验证码是否过期
5. 删除redis中的短信验证码
6.判断验证码的正确性
7.创建用户对象
8.设置用户属性
9.保存到数据库
10. 返回响应
:return:
"""
# json_data = request.data
# dict_data = json.loads(json_data)
# 下面这句话等同于上面两句
dict_data = request.json
mobile = dict_data.get('mobile')
sms_code = dict_data.get('sms_code')
password = dict_data.get('password')
# 2.校验参数
if not all([mobile,sms_code,password]):
return jsonify(errno=RET.PARAMERR,errmsg="参数不全")
# 3. 通过手机号取出验证码
try:
redis_sms_code = redis_store.get('sms_code:%s'%mobile)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR,errmsg="获取短信验证码异常")
#判断短信验证码是否过期
if not redis_sms_code:
return jsonify(errno=RET.NODATA,errmsg="短信验证码已经过期")
# 5. 删除redis中的短信验证码
try:
redis_store.delete('sms_code:%s' % mobile)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="删除短信验证码异常")
# 6.判断验证码的正确性
if redis_sms_code != sms_code:
return jsonify(errno=RET.DATAERR, errmsg="短信验证码错误")
# 7.创建用户对象
user = User()
# 8.设置用户属性
user.nick_name = mobile
user.password = password
user.mobile = mobile
# 9.保存到数据库
try:
db.session.add(user)
db.session.commit()
except Exception as e:
current_app.logger.error(e)
db.session.rollback()
return jsonify(errno=RET.DBERR, errmsg="用户注册失败")
# 10. 返回响应
return jsonify(errno=RET.OK, errmsg="用户注册成功")
- 打开info/static/news/js/main.js文件
// TODO 登录表单提交
$(".login_form_con").submit(function (e) {
// 阻止默认提交操作, 不让其往默认的action提交
e.preventDefault()
// 取到用户输入的内容
var mobile = $(".login_form #mobile").val()
var password = $(".login_form #password").val()
// 判断是否为空
if (!mobile) {
$("#login-mobile-err").show();
return;
}
if (!password) {
$("#login-password-err").show();
return;
}
// 发起注册请求
//拼接参数
var params = {
"mobile": mobile,
"password": password
}
$.ajax({
url: '/passport/login',//请求地址
type: 'post',
data: JSON.stringify(params),
contentType: 'application/json',
headers: {'X-CSRFToken': getCookie('csrf_token')},
success: function (resp) {
//判断是否请求成功
if (resp.errno == '0') {
// 重新加载当前页面即可
alert("登录成功")
window.location.reload()
} else {//发送失败
alert(resp.errmsg);
}
}
})
})
// TODO 注册按钮点击
$(".register_form_con").submit(function (e) {
// 阻止默认提交操作, 不让其往默认的action提交
e.preventDefault()
// 取到用户输入的内容
var mobile = $("#register_mobile").val()
var sms_code = $("#smscode").val()
var password = $("#register_password").val()
// 判断是否为空
if (!mobile) {
$("#register-mobile-err").show();
return;
}
if (!sms_code) {
$("#register-sms-code-err").show();
return;
}
if (!password) {
$("#register-password-err").html("请填写密码");
$("#register-password-err").show();
return;
}
if (password.length < 6) {
$("#register-password-err").html("密码长度不能少于6位");
$("#register-password-err").show();
return;
}
// 发起注册请求
//拼接参数
var params = {
"mobile": mobile,
"sms_code": sms_code,
"password": password
}
$.ajax({
url: '/passport/register',//请求地址
type: 'post',
data: JSON.stringify(params),
contentType: 'application/json',
headers: {'X-CSRFToken': getCookie('csrf_token')},
success: function (resp) {
//判断是否请求成功
if (resp.errno == '0') {
// 重新加载当前页面即可
alert("注册成功")
window.location.reload()
} else {//发送失败
alert(resp.errmsg);
}
}
})
})
})
-
运行程序
-
我们将数据库的passwor_hash里面的数据改成我们设的密码
-
运行程序
-
打开redis数据库,查看数据
以上项目可在我的GitHub上面查看:
(此文章仅作为个人学习笔记使用,如有错误欢迎指正~)
网友评论