账户登陆
我们在我们的passport中写入用户登陆的代码
这里就是我们要接受的信息
# 接受参数
request_dict = request.get_json()
mobile = request_dict.get('mobile')
password = request_dict.get('password')
然后校验参数和手机号
# 校验参数 看着两个参数存不存在
if not all([mobile,password]):
return jsonify(errno=RET.PARAMERR,errmsg='参数不完整')
# 验证手机号 --正则表达式
if not re.match(r'1[345678]\d{9}',mobile):
return jsonify(errno=RET.PARAMERR,errmag='手机号格式错误')
业务逻辑
从数据库中查询手机号是否存在
# 业务逻辑处理
# 从数据库中查询手机号是否存在
try:
User.query.filter_by(mobile=mobile).first()
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmag='获取用户信息失败')
接下来,如果手机号存在,验证密码
我们需要定义一个验证密码的方法在我们的models模型中
我们在模型中定义方法,直接调用这个验证密码的方法
接下来验证密码,保存登陆状态,然后返回
# 如果存在,验证密码,加not做一个取反
if user is None or not user.check_pwd_hash(password):
return jsonify(errno=RET.DATAERR,errmag='账号密码不匹配')
# 如果密码正确,保存登陆状态
session['name'] = user.name
session['mobile'] = user.mobile
session['user_id'] = user.id
# 返回
return jsonify(errno=RET.OK,errmag='登陆成功')
然后进入网址,输入之前注册的账号密码,登陆成功
接下来我们看看我们的代码有没有可以优化的地方
我们可以发现我们如果密码不正确,就可以一直试,直到密码正确
我们应该加上限制,如果同一个ip密码登陆错误几次之后,就一定时间内不能再登陆了
判断错误次数是否超限制,如果超过限制直接返回
我们只定义了怎么查询,接下来我们该向redis中添加用户的查询次数了
我们应该在验证密码那一步进行添加
这里我们使用了incr这个命令,如果后面的key没有值,则会默认传入1,如果再次调用这个命令,这个key会在原有的基础上加1
expirt命令是指定key的过期时间
我们在网站中试一下
到现在我们的登陆界面就搞完了
rt User
from lghome import db
from sqlalchemy.exc import IntegrityError
from lghome import constans
@api.route("/users", methods =["POST"])
def register():
"""
注册
:param: 手机号 短信验证码 密码 确认密码
:return: json
"""
# 接受参数,从前端
request_dict = request.get_json()
# print(request_dict) # 证明输出的是字典
mobile = request_dict.get("mobile")
sms_code = request_dict.get("sms_code")
password = request_dict.get("password")
password2 = request_dict.get("password2")
# 验证
if not all([mobile,sms_code,password,password2]):
return jsonify(errno=RET.PARAMERR,errms='参数不完整')
# 判断手机号格式
if not re.match(r'1[345678]\d{9}',mobile):
return jsonify(errno=RET.PARAMERR,errms='手机号格式错误')
if password != password2:
return jsonify(errno=RET.PARAMERR,errms='两次密码不一致')
# 业务逻辑
# 从redis取短信验证码
try:
real_sms_code = redis_store.get("sms_code_%s" % mobile)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg='读取短信验证码异常')
# 判断短信验证码是否过期
if real_sms_code is None:
return jsonify(errno=RET.NODATA, errmsg='短信验证码失效')
# 删除redis中的短信验证码
try:
redis_store.delete("sms_code_%s" % mobile)
except Exception as e:
logging.error(e)
# 判断用户填写的验证码的正确性
real_sms_code = real_sms_code.decode() # 转码,转换成字符串
if real_sms_code != sms_code:
return jsonify(errno=RET.DATAERR, errmsg='短信验证码错误')
# 如果用户填写的验证码正确
# 判断手机号是否存在(在获取短信验证码的时候已经做过一次了,但是有过期问题,以防万一可以在验证一次)
# try:
# user = User.query.filter_by(mobile=mobile).first()
# except Exception as e:
# logging.error(e)
# else:
# if user is not None:
# # 表示手机好已经被注册过
# return jsonify(errno=RET.DATAERR,errmsg='手机号已经存在')
# 保存数据
user = User(name=mobile,mobile=mobile) # 密码需要加密所以先不写密码
# 加密密码
user.password = password # password_hash = generate_password_hash(password)
# user(name=mobile,mobile=mobile,password_hash='加密之后的密码')
try:
db.session.add(user)
db.session.commit()
except IntegrityError as e:
db.session.rollback()
logging.error(e)
return jsonify(errno=RET.DATAEXIST, errmsg='手机号已经存在')
except Exception as e:
# 回滚
db.session.rollback()
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg='插入数据库异常')
# 保存登陆状态到session中
session["name"] = mobile
session["mobile"] = mobile
session["user_id"] = user.id
# 返回结果
return jsonify(errno=RET.OK,errmsg='注册成功')
@api.route('/sessions', methods =["POST"])
def login():
"""
用户登陆
:param: 手机号,密码
:return: json
"""
# 接受参数
request_dict = request.get_json()
mobile = request_dict.get('mobile')
password = request_dict.get('password')
# 校验参数 看着两个参数存不存在
if not all([mobile,password]):
return jsonify(errno=RET.PARAMERR,errmsg='参数不完整')
# 验证手机号 --正则表达式
if not re.match(r'1[345678]\d{9}',mobile):
return jsonify(errno=RET.PARAMERR,errms='手机号格式错误')
# 业务逻辑处理
# 判断错误次数是否超限制,如果超过限制直接返回
# redis 用户ip地址:次数
user_ip = request.remote_addr
try:
# bytes
access_nums = redis_store.get("access_nums_%s" % user_ip)
except Exception as e:
logging.error(e)
else:
# 判断次数,从redis中取出来的是一个字节,不能和整数比
if access_nums is not None and int(access_nums) >= constans.LOGIN_ERROR_MAX_TIMES:
return jsonify(errno=RET.REQERR,errmsg='错误次数太多,请稍后重试')
# 从数据库中查询手机号是否存在
try:
user = User.query.filter_by(mobile=mobile).first()
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg='获取用户信息失败')
# 如果存在,验证密码,加not做一个取反
if user is None or not user.check_pwd_hash(password):
try:
redis_store.incr("access_nums_%s" % user_ip)
redis_store.expire("access_nums_%s" % user_ip,constans.LOGIN_ERROR_FORBID_TIME) # 设置过期时间
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DATAERR,errmsg='账号密码不匹配')
# 如果密码正确,保存登陆状态
session['name'] = user.name
session['mobile'] = user.mobile
session['user_id'] = user.id
# 返回
return jsonify(errno=RET.OK,errmsg='登陆成功')