web项目024-----账户登陆

账户登陆

image.png

我们在我们的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='登陆成功')

 

 

 

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页