Django 用户的修改密码接口
实现修改密码接口
请求方式: POST
修改请求参数 : /change_pwd/
业务处理流程:
验证手机号是否注册 (格式, ajax请求检查)
原密码是否正确 (格式,null, 数据库检查)
新密码是否正确 (格式, null, 存数据库)
参数 | 是否前端传入 | 描述 | 类型 |
mobile | 是 | 用户输入的手机号 | 字符串 |
old_password | 是 | 用户输入要修改的密码 | 字符串 |
new_password | 是 | 用户输入的新密码 | 字符串 |
sms_code | 是 | 用户输入的短信验证码 | 字符串 |
注:由于是post请求,在向后端发起请求时,需要附带csrf token
前端代码 (毕竟是前端发送ajax请求的)
$(function () { let $mobile = $('#mobile'); let $smsCodeBtn = $('.form-item .sms-captcha'); // 获取短信验证码按钮元素,需要定义一个id为input_smscode let $submit = $('.form-contain'); // 手机号检测 $mobile.blur(function () { fn_check_mobile(); }); // 短信验证码发送 $smsCodeBtn.click(function () { // 判断手机号是否输入 if (fn_check_mobile() !== "success") { return } let SdataParams = { "mobile": $mobile.val(), // 获取用户输入的手机号 }; $.ajax({ //请求地址 url : "/change_pwd/sms_code/", //请求方式 type: "POST", data: JSON.stringify(SdataParams), contentType: "application/json; charset=utf-8", dataType : "json", async: false, }) .done(function (res) { if (res.errno === "0") { // 倒计时60秒,60秒后允许用户再次点击发送短信验证码的按钮 message.showSuccess('短信验证码发送成功'); let num = 60; // 设置一个计时器 let t = setInterval(function () { if (num === 1) { // 如果计时器到最后, 清除计时器对象 clearInterval(t); // 将点击获取验证码的按钮展示的文本恢复成原始文本 $smsCodeBtn.html("获取验证码"); } else { num -= 1; // 展示倒计时信息 $smsCodeBtn.html(num + "秒"); } }, 1000); } else { message.showError(res.errmsg); } }) .fail(function () { message.showError('服务器超时,请重试!'); }); }); // 确认修改密码 $submit.submit(function (e) { e.preventDefault(); //获取用户输入的内容 let sMobile = $mobile.val(); let soldPassword = $("input[name=old_password]").val(); let snewPassword = $("input[name=new_password]").val(); let sSmsCode = $("input[name=sms_captcha]").val(); if (fn_check_mobile() !== "success") { return } // 判断用户输入的密码是否为空 if ((!soldPassword) || (!snewPassword)) { message.showError('密码或确认密码不能为空'); return } // 判断用户输入的密码和确认密码长度是否为6-20位 if (!(/^[0-9A-Za-z]{6,20}$/).test(snewPassword)) { message.showError('新密码的长度需在6~20位以内'); return } // 判断用户输入的密码和确认密码长度是否为6-20位 if (!(/^[0-9A-Za-z]{6,20}$/).test(soldPassword)) { message.showError('原密码的长度需在6~20位以内'); return } // 密码不能一样 if (soldPassword == snewPassword) { message.showError('原密码和新密码一致,请重新检查并输入'); return } //短信验证码格式 if (!(/^\d{6}$/).test(sSmsCode)) { message.showError('短信验证码格式不正确,必须为6位数字!'); return } //发起POST请求 let SdataParams = { "mobile": sMobile, "old_password": soldPassword, "new_password": snewPassword, "sms_code": sSmsCode, }; $.ajax({ url: "/change_pwd/", type: "POST", headers: { "X-CSRFToken": getCookie("csrf_token") }, data: JSON.stringify(SdataParams), contentType: "application/json; charset=utf-8", dataType: "json", }) .done(function (res) { if (res.errno === "0") { // 注册成功 message.showSuccess('恭喜你, 修改成功!'); setTimeout(function () { // 注册成功之后重定向到主页 window.location.href = document.referrer; }, 1000) } else { // 注册失败,打印错误信息 message.showError(res.errmsg); } }) .fail(function(){ message.showError('服务器超时,请重试!'); }); }); // 检查手机号是否被注册 function fn_check_mobile() { let sMobile = $mobile.val(); // 获取用户输入的手机号码字符串 let sReturnValue = ""; if (sMobile === "") { message.showError('手机号不能为空'); return } if (!(/^1[345789]\d{9}$/).test(sMobile)) { message.showError('手机号码格式不正确,请重新输入!'); return } $.ajax({ url: 'change_pwd/mobiles/' + sMobile + '/', type: 'GET', dataType: 'json', async: false }) .done(function (res) { if (res.data.count == 0) { message.showError(res.data.mobile + '尚未注册,请重新输入!'); sReturnValue = "" } else { message.showSuccess(res.data.mobile + '号码正确'); sReturnValue = "success" } }) .fail(function () { message.showError('服务器超时,请重试!'); sReturnValue = "" }); return sReturnValue } function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { let cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { let cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } });
后端
class ChangePwdMobile(View): """ Check whether the user exists in ChangePwd page GET mobiles/(?P<mobile>1[3-9]\d{9})/ """ def get(self, request, mobile): data = { 'mobile': mobile, 'count': Users.objects.filter(mobile=mobile).count() } return to_json_data(data=data)
class ChangePwdSmsCode(View): """ send sms_code in changePwd """ def post(self, request): try: json_data = request.body if not json_data: return to_json_data(errno=Code.PARAMERR, errmsg="参数为空,请重新输入") dict_data = json.loads(json_data.decode('utf8')) except Exception as e: logger.info('错误信息: {}'.format(e)) return to_json_data(errno=Code.UNKOWNERR, errmsg="未知错误") mobile = dict_data.get('mobile') if not mobile: return to_json_data(errno=Code.PARAMERR, errmsg='参数错误') # 发送短信频繁 try: con_redis = get_redis_connection(alias='changePwd_codes') except Exception as e: # 日志器 return to_json_data(Code.UNKOWNERR, errmsg='未知错误') send_flag = con_redis.get('sms_flag_{}'.format(mobile)) if send_flag: return to_json_data(errno=Code.DATAEXIST, errmsg='发送短信频繁') sms_num = '%06d' % random.randint(0, 999999) print(sms_num) # 保存 redis_con = get_redis_connection(alias='changePwd_codes') # 短信验证码 写key sms_text = "sms_{}".format(mobile).encode('utf-8') # 过期时间 sms_flag = "sms_flag_{}".format(mobile).encode('utf-8') p2 = redis_con.pipeline() # 保存验证码 try: p2.setex(sms_text, constant.SMS_CODE_REDIS_EXPIRES, sms_num) p2.setex(sms_flag, constant.SEND_SMS_CODE_INTERVAL, 1) p2.execute() except Exception as e: logger.debug("redis 执行出现异常 {}".format(e)) return to_json_data(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR]) # 发送验证码 logging.info("发送验证码短信【成功】[mobile:{}, sms_code:{}]".format(mobile, sms_num)) return to_json_data(errno=Code.OK, errmsg="短信验证码发送成功")
class ChangePwd(View): """ get : change_pwd page post: submit """ def get(self, request): return render(request, 'users/change_pwd.html') def post(self, request): json_str = request.body if not json_str: return to_json_data(errno=Code.PARAMERR, errmsg='参数为空') dict_data = json.loads(json_str.decode('utf-8')) mobile = dict_data.get('mobile') old_password = dict_data.get('old_password') new_password = dict_data.get('new_password') sms_code = dict_data.get('sms_code') # 是否为空 if not all([mobile, old_password, new_password, sms_code]): return HttpResponseForbidden('输入为空') # 手机格式 if not re.match('^1[3-9]\d{9}$', mobile): return HttpResponseForbidden('手机号码格式输入错误') # 原密码格式错误 if not re.match('^[0-9A-Za-z]{6,20}$', old_password): return HttpResponseForbidden('新密码格式不正确') # 新密码格式 if not re.match('^[0-9A-Za-z]{6,20}$', new_password): return HttpResponseForbidden('新密码格式不正确') # 原密码和新密码 if new_password == old_password: return HttpResponseForbidden('原密码和新密码相同,请重试') # 验证码格式是否正确 if not sms_code.isnumeric(): return ("请重新检查你的验证码是否正确 Forms ") # 拿到当前对象user user = Users.objects.get(mobile=mobile) if user: if check_password(old_password, user.password): user.set_password(new_password) user.save() return to_json_data(errno=Code.OK, errmsg='恭喜你修改成功') else: return to_json_data(errno=Code.PARAMERR, errmsg='原密码错误') else: return to_json_data(errno=Code.PARAMERR, errmsg='不存在当前用户')
URL配置
path('change_pwd/', views.ChangePwd.as_view(), name='change_pwd'),