第一步:注册后端逻辑补充
我们上一次的注册代码写了一些还没写完,现在来把它补完。(注意有些代码需要导包)
@passport_blue.route("/register",methods = ["post"]) def register(): """注册 1.接受参数(手机号,短信验证码,密码明文) 2.校验参数(判断是否缺少和手机号是否合法) 2.1检查参数是否齐全 2.2校验手机号是否合法 2.3检查短信验证码是否正确 读取redis中存储的短信验证码 检查是否读取到该信息 对比 3.建立模型类对象 密码加密问题 4.提交到数据库中 5.保存session,实现状态保持,注册即登录 6.响应注册结果 :return: """ # 1.接受参数(手机号,短信验证码,密码明文) res_dict = request.json #相当于json.loads(request.data) mobile = res_dict.get("mobile") smscode = res_dict.get("smscode") password = res_dict.get("password") # 2.校验参数(判断是否缺少和手机号是否合法) # 2.1检查参数是否齐全 if not all([mobile,smscode,password]): return jsonify(errno=RET.PARAMERR,errmsg="缺少参数") # 2.2校验手机号是否合法 if not re.match("^1[3789][0-9]{9}$", mobile): # 这里我们指定了第二位是3789其中的一位,如果判断手机号不合法 return jsonify(errno=RET.PARAMERR, errmsg="手机号不合法") # 2.3检查短信验证码是否正确 # 读取redis中存储的短信验证码 try: sms_code_server = redis_store.get("sms_code:"+mobile) except Exception as e: current_app.logger.error(e) return jsonify(errno=RET.DBERR,errmsg="手机验证码读取失败") # 检查是否读取到该信息 if not sms_code_server: return jsonify(errno=RET.NODATA,errmsg="未读取到手机验证码") # 对比 if sms_code_server != smscode: return jsonify(errno=RET.PARAMERR,errmsg="手机验证码错误") # 3.建立模型类对象 user = User() user.mobile = mobile user.nick_name = mobile user.last_login = datetime.datetime.now() # 密码加密问题 user.password = password # 4.提交到数据库中 try: db.session.add(user) db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rollback() return jsonify(errno=RET.PARAMERR,errmsg="手机验证码错误") # 5.保存session, 实现状态保持,注册即登录 session["mobile"] = user.mobile session["id"] = user.id session["nick_name"] = user.nick_name # 6.响应注册结果 return jsonify(errno=RET.OK,errmsg="注册成功")
这里有一个要注意的地方就是密码加密。
关于密码加密通常有三种方式:
- 方案一:在这个视图中,直接调用对应的密码加密的算法,加密密码存储到数据库
- 方案二:在这个视图中,封装一个加密的方法,加密密码存储到数据库
- 方案三:在模型类中新增一个属性叫做password,并加载setter和getter方法,调用setter方法,直接完成密码的加密存储
前两种方式会将加密方式暴露在视图中,所以这个项目中使用的密码加密方式是第三种,这种方法也是对python面向对象和程序设计时降低代码耦合度的较好体现。
我们需要去到info的models里去写入加密代码,在用户下方隔两层再写
@property def password(self): return "you can't read" @password.setter def password(self, value): self.password_hash = generate_password_hash(value)
这里有一个快捷键props。
第二步:注册前端逻辑补充
我们后端代码写好后去运行代码,注册之后应该要有一个刷新页面,但现在并没有,那是因为我们前端还没处理好。
现在我们就需要去写前端,去到info.templates的index.html里,在这里我们要按几次shift,然后输入main.js进入
进到这里,我们要找到发起注册请求,找到你会发现这里是空的,所以我们要给它填上
// 发起注册请求 var params = { 'mobile':mobile, 'smscode':smscode, 'password':password }; $.ajax({ url:'/passport/register', // 请求地址 type:'post', // 请求方法 data:JSON.stringify(params), // 请求参数 contentType:'application/json', headers:{'X-CSRFToken':getCookie('csrf_token')}, // 在请求头中带上csrf_token success:function (response) { if (response.errno == '0') { // 注册成功 location.reload(); } else { alert(response.errmsg); } } });
前端和后端都写好,就可以测试一下,如果测试成功你的数据库就会有这些
第三步:登录后端逻辑
注册写完,我们就该可以写登录了,还是老方法先写逻辑然后根据表写接口
代码:
@passport_blue.route("/login",methods = ["POST"]) def login(): """ 1.接收参数(手机号,密码) 2.校验参数 2.1校验参数是否齐全 2.2校验手机号 利用手机号从数据库中找到对应的用户信息 如果没有代表没有该用户 2.3校验密码 注意加密位置 3.写入session数据 4.更新最后一次登录时间 2.返回内容 :return: """ # 1.接收参数(手机号,密码) res = request.json mobile = res.get("mobile") password = res.get("password") # 2.校验参数 # 2.1校验参数是否齐全 if not all([mobile,password]): return jsonify(errno=RET.PARAMERR,errmsg="缺少参数") # 2.2校验手机号 if not re.match("^1[3789][0-9]{9}$", mobile): # 这里我们指定了第二位是3789其中的一位,如果判断手机号不合法 return jsonify(errno=RET.PARAMERR, errmsg="手机号不合法") # 利用手机号从数据库中找到对应的用户信息 try: user = User.query.filter_by(mobile=mobile).first() # User.query.filter(User.mobile == mobile).first() except Exception as e: return jsonify(errno=RET.DBERR,errmsg="数据库查询失败") # 如果没有代表没有该用户 if not user: return jsonify(errno=RET.NODATA,errmsg="没有找到该用户") # 2.3校验密码 if not user.check_password(password): return jsonify(errno=RET.PWDERR, errmsg="用户名或者密码错误") # 3.写入session数据 session["mobile"] = user.mobile session["id"] = user.id session["nick_name"] = user.nick_name # 4.更新最后一次登录时间 user.last_login = datetime.datetime.now() try: db.session.commit() except Exception as e: current_app.logger.error(e) db.session.rolback() return jsonify(errno=RET.DATAERR,errmsg="数据库更新失败") # 2.返回内容 return jsonify(errno=RET.OK, errmsg="登录成功")
代码里我们有要注意的地方
首先我们的密码是加密的而我要校验密码的话肯定是校验不了的,所以我们需要去改一下
去到info的models里我们加密密码下加入代码
def check_password(self, password): """ 用于校验密码 :param password: 要检验的密码的明文 :return: 返回校验的结果 True/False """ return check_password_hash(self.password_hash, password)
第四步:登录前端逻辑
这里和注册的一样,我们去到main.js里加入登录代码
// 发起登录请求 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')}, // 在请求头中带上csrf_token success:function (response) { if (response.errno == '0') { // 登录成功后刷新当前界面 location.reload(); } else { alert(response.errmsg); } } });