Selaa lähdekoodia

单点登录修改密码

peng 1 vuosi sitten
vanhempi
commit
5767fc21a2
3 muutettua tiedostoa jossa 212 lisäystä ja 4 poistoa
  1. 1 0
      Ansjer/urls.py
  2. 209 4
      Controller/UserController.py
  3. 2 0
      Object/ResponseObject.py

+ 1 - 0
Ansjer/urls.py

@@ -163,6 +163,7 @@ urlpatterns = [
     re_path(r'^wechat/perfect', UserController.wxPerfectView.as_view()),
     re_path(r'^Test', Test.Test.as_view()),
     re_path(r'^oauth/authcode', UserController.OauthAuthCodeView.as_view()),
+    re_path(r'^single/login/(?P<operation>.*)$', UserController.SingleLoginView.as_view()),
     re_path(r'^oauth/perfect', UserController.OauthPerfectView.as_view()),
     re_path(r'^oauth/unbunding', UserController.UnbundingWXView.as_view()),
     re_path(r'^equipment/judge', EquipmentManager.judgeInterface),

+ 209 - 4
Controller/UserController.py

@@ -475,7 +475,8 @@ class v3ChangePwdView(TemplateView):
             response.lang = tko.lang
             if tko.code != 0:
                 return response.json(tko.code)
-            return self.updatePwd(tko.userID, oldPwd, newPwd, response, password_version, new_salt, old_salt, iterations)
+            return self.updatePwd(tko.userID, oldPwd, newPwd, response, password_version, new_salt, old_salt,
+                                  iterations)
 
     def updatePwd(self, userID, oldPwd, newPwd, response, password_version, new_salt, old_salt, iterations):
         user_qs = Device_User.objects.filter(userID=userID)
@@ -985,7 +986,6 @@ class v2authCodeView(TemplateView):
         )
         return send_res
 
-
     def phoneCode(self, phone, response, sign_name):
         dataValid = DataValid()
         if dataValid.mobile_validate(phone) is not True:
@@ -1386,9 +1386,11 @@ class v3registerView(TemplateView):
                 create_data["region_country"] = number
             Device_User.objects.create(**create_data)
             if push_scription:
-                UserEmailSubscriptions.objects.create(phone=phone, user_id=userID, push_sub_status=1, created_time=int(time.time()), updated_time=int(time.time()))
+                UserEmailSubscriptions.objects.create(phone=phone, user_id=userID, push_sub_status=1,
+                                                      created_time=int(time.time()), updated_time=int(time.time()))
             else:
-                UserEmailSubscriptions.objects.create(phone=phone, user_id=userID, push_sub_status=0, created_time=int(time.time()), updated_time=int(time.time()))
+                UserEmailSubscriptions.objects.create(phone=phone, user_id=userID, push_sub_status=0,
+                                                      created_time=int(time.time()), updated_time=int(time.time()))
 
         except Exception as e:
             errorInfo = traceback.format_exc()
@@ -3336,6 +3338,209 @@ class OauthPerfectView(TemplateView):
         return response.json(0)
 
 
+class SingleLoginView(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(SingleLoginView, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request, request.GET, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request, request.POST, operation)
+
+    def validation(self, request, request_dict, operation):
+        lang = request_dict.get('lang', 'en')
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        if operation == 'get-verification-code':  # 获取验证码
+            return self.get_verification_code(request_dict, response)
+        elif operation == 'change-password':  # 验证码修改密码
+            return self.change_password(request_dict, response)
+        else:
+            return response.json(404)
+
+    def get_verification_code(self, request_dict, response):
+        email = request_dict.get('email', None)
+        phone = request_dict.get('phone', None)
+        sign_name = request_dict.get('sign_name', None)
+        country_code = request_dict.get('country_code', None)
+        if email is not None:
+            email = email.strip()
+            # 阿里云的发送邮箱的调用方法
+            return self.get_aliyun_email_code(email, response)
+        elif phone is not None:
+            phone = phone.strip()
+            country_code = str(country_code.strip())
+            return self.get_phone_code(country_code, phone, response, sign_name)
+        else:
+            return response.json(444)
+
+    @staticmethod
+    def get_aliyun_email_code(email, response):
+        print('阿里云开始')
+        data_valid = DataValid()
+        # 邮箱匹配
+        if data_valid.email_validate(email) is False:
+            return response.json(107)
+        reds = RedisObject()
+        identifying_code = reds.get_data(key=email + '_SingleLogin')
+        # 是否以获取邮箱验证码
+        if identifying_code:
+            return response.json(89)
+        user_qs = Device_User.objects.filter(Q(username=email) | Q(userEmail=email))
+        # 邮箱用户是否已存在
+        if not user_qs.exists():
+            return response.json(99)
+        # 生成随机6位数
+        identifying_code = RandomStr(6, True)
+        # 设置随机数缓存生命周期
+        send_data = TemplateService.email_message(type='register_code', language=response.lang)
+        ses = SesClassObject()
+        # 发送邮件
+        send_res = ses.alyEmailCode(
+            send_address_list=[email],
+            subject=send_data['title'],
+            body=send_data['body'].replace("{username}", email).replace("{captcha}", str(identifying_code))
+        )
+        if send_res is not True:
+            return response.json(44)
+        if reds.set_data(key=email + '_SingleLogin', val=identifying_code, expire=600) is not True:
+            return response.json(10, 'error')
+        return response.json(0)
+
+    @staticmethod
+    def get_phone_code(country_code, phone, response, sign_name):
+        data_valid = DataValid()
+        if data_valid.mobile_validate(phone) is not True:
+            return response.json(107)
+        reds = RedisObject()
+        reds_key = str(phone) + '_SingleLogin'
+        identifying_code = reds.get_data(key=reds_key)
+        reds_key_ttl = reds.get_ttl(key=reds_key)
+        if reds_key_ttl > 240 and identifying_code:
+            return response.json(90)
+        user_qs = Device_User.objects.filter(Q(username=phone) | Q(phone=phone))
+        if not user_qs.exists():
+            return response.json(102)
+        identifying_code = RandomStr(6, True)
+        if country_code == '86':
+            # 国内短信推送模板
+            temp_msg = 'SMS_151600991'
+            rec_phone = phone
+            if sign_name == 'zosi':
+                sign_ms = '周视'
+            else:
+                sign_ms = 'Ansjer'
+        else:
+            # 国际短信推送模板
+            temp_msg = 'SMS_172165867'
+            rec_phone = country_code + phone
+            sign_ms = 'Ansjer'
+
+        # 发送手机验证码
+        alisms = AliSmsObject()
+        res = alisms.send_code_sms(phone=rec_phone, code=identifying_code, sign_name=sign_ms, temp_msg=temp_msg)
+        if res["Code"] == "OK":
+            if reds.set_data(key=reds_key, val=identifying_code, expire=300) is not True:
+                return response.json(10, '生成缓存系统错误')
+            return response.json(0)
+        else:
+            return response.json(10, res["Message"])
+
+    def change_password(self, request_dict, response):
+        phone = request_dict.get('phone', None)
+        email = request_dict.get('email', None)
+        password = request_dict.get('password', None)
+        salt = request_dict.get('salt', None)
+        password_version = request_dict.get('pwdVersion', 'V1')
+        authcode = request_dict.get('authcode', None)
+        if password is None or authcode is None:
+            return response.json(444, 'password,authcode')
+        authcode = CommonService.decode_data(authcode.strip())
+        if authcode is None:
+            return response.json(444, 'password,authcode')
+
+        password = CommonService.decode_data(password.strip())
+        if password is None:
+            return response.json(444, 'password,authcode')
+        if phone is not None:
+            phone = phone.strip()
+            return self.do_phone(phone, authcode, password, response, password_version, salt)
+        elif email is not None:
+            email = email.strip()
+            return self.do_email(email, authcode, password, response, password_version, salt)
+        else:
+            return response.json(444, 'phone')
+
+    @staticmethod
+    def do_email(email, authcode, password, response, password_version, salt):
+        data_valid = DataValid()
+        if data_valid.email_validate(email) is not True:
+            return response.json(105)
+        # 邮箱用户是否已存在
+        user_qs = Device_User.objects.filter(Q(username=email) | Q(userEmail=email))
+        if not user_qs.exists():
+            return response.json(99)
+        if password_version == 'V1':
+            re_flag = data_valid.password_validate(password)
+            password = make_password(password)
+        else:
+            if not salt:
+                return response.json(111)
+            password = "%s$%d$%s$%s" % ("pbkdf2_sha256", 260000, salt, password)
+            re_flag = True
+        if re_flag is not True:
+            return response.json(109)
+        reds = RedisObject()
+        key = email + '_SingleLogin'
+        reset_code = reds.get_data(key=key)
+        if reset_code is False:
+            return response.json(90)
+        if authcode != reset_code:
+            return response.json(121)
+        user_qs.update(userEmail=email, password=password)
+        if not reds.del_data(key):
+            return response.json(10, '删除缓存失败')
+        return response.json(0)
+
+    @staticmethod
+    def do_phone(phone, authcode, password, response, password_version, salt):
+        data_valid = DataValid()
+        if data_valid.mobile_validate(phone) is not True:
+            return response.json(100)
+        user_qs = Device_User.objects.filter(Q(username=phone) | Q(phone=phone))
+        if not user_qs.exists():
+            return response.json(102)
+        if password_version == 'V1':
+            re_flag = data_valid.password_validate(password)
+            password = make_password(password)
+        else:
+            if not salt:
+                return response.json(111)
+            password = "%s$%d$%s$%s" % ("pbkdf2_sha256", 260000, salt, password)
+            re_flag = True
+        if re_flag is not True:
+            return response.json(109)
+        reds = RedisObject()
+        key = str(phone) + '_SingleLogin'
+        reset_code = reds.get_data(key=key)
+        if reset_code is False:
+            return response.json(90)
+        if authcode != reset_code:
+            return response.json(121)
+        user_qs.update(phone=phone, password=password)
+        if not reds.del_data(key):
+            return response.json(10, '删除缓存失败')
+        return response.json(0)
+
+
 class UnbundingWXView(TemplateView):
 
     def get(self, request, *args, **kwargs):

+ 2 - 0
Object/ResponseObject.py

@@ -57,6 +57,7 @@ class ResponseObject(object):
             201: 'You can only add 3 custom voice at most',
             306: 'The link has expired!',
             309: 'Please ReLogin! errmsg token',
+            310: 'Your account is being logged in on another device, if it was not done by yourself, please change your password immediately!',
             404: 'You don not have permission to access this!',
             414: 'Please confirm the request url!',
             424: 'Database Error !',
@@ -200,6 +201,7 @@ class ResponseObject(object):
             201: '最多只能添加3条自定义语音',
             306: '链接已超过有效期!',
             309: '请重新登录!',
+            310: '检测到您的账号在另一台设备上登录,如非本人操作,请立即修改密码!',
             404: '您没有访问的权限!',
             414: '请确认请求url!',
             424: '数据库错误!',