项目简要分析2
注册接口
使用单例模式重构云通信的发送短信的demo,有空看下
接口文档
url : /avi/v1_0/users/
请求的方式:POST
发送数据类型:json
必传的参数:mobile,sms_code,password
返回结果
类型:json
参数:errno,errmsg
获取前端的参数有
resp_dict = request.get_json() mobile = resp_dict.get('mobile') sms_code = resp_dict.get('sms_code') password = resp_dict.get('password')
检查上述数据的完整性
if not all([mobile, sms_code, password]): resp = { 'errno': RET.PARAMERR, 'errmsg': '参数不完整' } return jsonify(resp)
检查手机号码的有效性
if not re.match(r'1[34578]\d{9}', mobile): resp = { 'errno': RET.DATAERR, 'errmsg': '手机号格式错误' } return jsonify(resp)
业务逻辑处理
从redis中获取短信的验证码
real_sms_code = redis_store.get('sms_code_' + mobile)
判断验证码是否过期
if real_sms_code is None: resp = { 'errno': RET.NODATA, 'errmsg': '短信验证码已过期' } return jsonify(resp)
判断用户是否输出了正确的验证码
if real_sms_code != sms_code:
resp = {
'errno': RET.DATAERR,
'errmsg': '短信验证码填写错误'
}
return jsonify(resp)
删除验证码
redis_store.delete('sms_code_' + mobile)
保存用户的数据(牵扯到数据库的回滚操作)
# 创建用户, 保存数据 user = User(name=mobile, mobile=mobile) # 密码的处理, 应该交给模型类去处理. user.password = password try: db.session.add(user) db.session.commit() except Exception as e: # a. 记录日志 logging.error(e) # b. 回滚操作 db.session.rollback() # c. 返回错误数据 resp = { 'errno': RET.NODATA, 'errmsg': '短信验证码已过期' } return jsonify(resp)
可以设置session的信息
session['user_id'] = user.id session['user_name'] = mobile session['mobile'] = mobile
以上都正确的话注册成功
resp = { 'errno': RET.OK, 'errmsg': '注册成功' } return jsonify(resp)
用户登陆接口
接口文档
url : /avi/v1_0/session/
请求的方式:POST
发送数据类型:json
必传的参数:mobile,password
返回结果
类型:json
参数:errno,errmsg
后端业务逻辑分析
一 接受参数
接受参数 手机号,密码
二 参数校验
总体的参数校验
校验手机号的完整性
三 获取用户的ip地址
获取用户输入的错误次数
判断用户输入的次数是否超过5次
检验用户和密码是否匹配
四 以上都正确删除,redis中用户输入错误的次数
五 设置session 信息
六 返回给前端结果
分析逻辑如下:
获取前端传的参数
resp_json = request.get_json()
mobile = resp_json.get('mobile')
password = resp_json.get('password')
检验参数的完整性
if not all([mobile, password]): return jsonify(errno = RET.PARAMERR, errmsg = '参数不完整')
判断用户在redis中输入错误的次数,如果存在并且错误的次数超过5次,不需判断直接返回即可,在10分钟后才可以继续登录
user_ip = request.remote_addr access_counts = redis_store.get('access_' + user_ip) if access_counts is not None and int(access_counts) >= 5: return jsonify(errno=RET.REQERR, errmsg='请求已超过最大次数')
查询数据库判断用户的信息与密码
如果用户不存在并且输入的密码和数据库中的不一致,错误的次数+1,,返回错误的信息
user = User.query.filter_by(mobile=mobile).first() if user is None or not user.check_password(password): # 累加错误次数, 并设置时间 try: # incr:累加错误次数 redis_store.incr('access_' + user_ip) # expire: 第一个参数 key, 第二个参数 过期时间 redis_store.expire('access_' + user_ip, 600) except Exception as e: logging.error(e) return jsonify(errno=RET.LOGINERR, errmsg='用户名或密码输入错误')
以上都完成说明用户登录的信息是正确的,用户登录成功,清除以前输入的错误次数
redis_store.delete('access_' + user_ip)
设置session信息,返回登录成功的信息
session['user_id'] = user.id session['user_name'] = mobile session['mobile'] = mobile # 四. 返回值 return jsonify(errno=RET.OK, errmsg='用户登录成功')
检查用户登录状态的接口
接口文档
url /sessions 请求方式: get 返回格式: { "data": { "name": "18001225173" }, "errmsg": "true", "errno": "0" }
尝试从session中获取用户的名字,如果存在说明用户已经登录,否则说明用户未登录
name = session.get("user_name") # 如果session中数据name名字存在,则表示用户已登录,否则未登录 if name is not None: return jsonify(errno=RET.OK, errmsg="true", data={"name": name}) else: return jsonify(errno=RET.SESSIONERR, errmsg="false")
判断用户是否登录的装饰器
如果用户已经登录的话,把用户的user.id保存到g变量中,g变量是随着程序的启动而生,停止而亡
def login_required(view_func): """检验用户的登录状态""" @wraps(view_func) def wrapper(*args, **kwargs): user_id = session.get("user_id") if user_id is not None: # 表示用户已经登录 # 使用g对象保存user_id,在视图函数中可以直接使用 # 比如后面设置头像的时候, 仍然需要获取session的数据. 为了避免多次访问redis服务器. 可以使用g变量 g.user_id = user_id return view_func(*args, **kwargs) else: # 用户未登录 resp = { "errno": RET.SESSIONERR, "errmsg": "用户未登录" } return jsonify(resp) return wrapper
登出接口
接口文档
url : sessions
请求的方式 : DELETE
清除session的数据
session.clear() return jsonify(errno=RET.OK, errmsg="OK")

浙公网安备 33010602011771号