# lghome/api_1_0/passport.py
@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')
print(mobile,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, errmsg='手机号格式错误')
# 判断业务逻辑处理
# 从数据库查询手机号是否存在
try:
user = User.query.filter_by(mobile=mobile).first()
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='获取信息失败')
# 验证密码
if user is None or not user.check_pwd_hash(password):
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='登录成功')
4.アルゴリズムの最適化
4.1エラーの数を制限する
エラーの数が制限されていない場合、アカウントのパスワードは悪意を持ってテストされます
一定期間内のエラー数を制限し、制限を超えた後はログインできません
パラメータを受け取った後、最初にフロントエンドIPが制限を超えているかどうかを判断します
IPが誤ってアクセスされた回数をredisから取得します
エラーの数が空ではなく、制限以上の場合、エラーは直接返されます
携帯電話番号が存在するか(登録ユーザーか)、パスワードが間違っているかどうかを確認し、
エラーが発生した場合、エラーの数は1増加し、redisに保存されます。
# 判断业务逻辑处理
# 判断错误次数是否超过限制,如果超过限制直接返回
# redis 用户IP地址:次数
user_ip = request.remote_addr
print(user_ip)
try:
access_nums=redis_store.get("access_nums_%s"%user_ip)
print("access_nums_%s"%user_ip,access_nums)
except Exception as e:
logging.error(e)
else:
if access_nums is not None and int(access_nums)>=constants.LOGIN_ERROR_MAX_TIMES:
return jsonify(errno=RET.REQERR, errmsg='错误次数太多,请稍后重试')
# 验证密码
# if user is None or not user.check_pwd_hash(password):
# return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
if user is None or not user.check_pwd_hash(password):
try:
redis_store.incr("access_nums_%s" % user_ip)
redis_store.repire("access_nums_%s"%user_ip,constants.LOGIN_ERROR_FORBID_TIME)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')
4.2エラー時間を節約するときにパイプラインを使用する
# 验证密码# if user is None or not user.check_pwd_hash(password):# return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')if user is None or not user.check_pwd_hash(password):
try:
# redis管道
pl = redis_store.pipeline()
pl.incr("access_nums_%s" % user_ip)
pl.repire("access_nums_%s"%user_ip,constants.LOGIN_ERROR_FORBID_TIME)
pl.execute()
except Exception as e:
logging.error(e)return jsonify(errno=RET.DATAERR, errmsg='帐号密码不匹配')