浏览代码

手机短信修改密码

peng 11 月之前
父节点
当前提交
9a8b95cc21
共有 3 个文件被更改,包括 327 次插入1 次删除
  1. 47 0
      Ansjer/config.py
  2. 1 0
      Ansjer/urls.py
  3. 279 1
      Controller/UserController.py

+ 47 - 0
Ansjer/config.py

@@ -528,3 +528,50 @@ SES_USERNAME_SMTP = 'AKIA2E67UIMD6MOSFKXW'  # 带有邮件权限的 IAM 帐号
 SES_PASSWORD_SMTP = 'BHuQ6EQTtFK4qh46o9omO9ZzO3NXzjk/JCWLXnVFmqzM'  # 带有邮件权限的 IAM 密码
 SES_PORT = '587'
 SES_HOST = 'email-smtp.us-east-1.amazonaws.com'
+
+APP_MAPPING = {
+    'com.ansjer.accloud': 'ACCloud',  # IOS
+    'com.ansjer.accloud_a': 'ACCloud',  # Android
+
+    'com.ansjer.adcloud': 'ADCloud',  # IOS
+    'com.ansjer.adcloud_a': 'ADCloud',  # Android
+
+    'com.ansjer.zccloud': 'ZosiSmart',  # IOS
+    'com.ansjer.zccloud_a': 'ZosiSmart',  # Android
+
+    'com.ansjer.loocamccloud': 'Loocam',  # IOS
+    'com.ansjer.loocamccloud_a': 'Loocam',  # Android
+
+    'com.ansjer.zosidcloud': 'Anlapus',  # IOS
+    'com.ansjer.zosidcloud_a': 'Anlapus',  # Android
+
+    'com.ansjer.customizeda': 'Guardian_365',  # IOS
+    'com.ansjer.customizeda_a': 'Guardian_365',  # Android
+
+    'com.ansjer.customizedb': 'COCOON_HD',  # IOS
+    'com.ansjer.customizedb_a': 'COCOON_HD',  # Android
+
+    'com.ansjer.customizede': 'ZOSI',  # IOS “周视”
+    'com.ansjer.zccloud_ab': 'ZOSI',  # Android “周视”
+
+    'com.ansjer.customizedd': 'DVS_Mobile',  # IOS
+    'com.ansjer.customizedd_a': 'DVS_Mobile',  # Android
+
+    'com.ansjer.loocamhome': 'Loocam_Home',  # IOS
+    'com.ansjer.loocamhome_a': 'Loocam_Home',  # Android
+
+    'com.ansjer.customizedc': 'PatrolSecure',  # IOS
+    'com.ansjer.customizedc_a': 'PatrolSecure',  # Android
+
+    'com.cloudlife.commissionf': 'VSees',  # IOS
+    'com.cloudlife.commissionf_a': 'VSees',  # Android
+
+    'com.ansjer.zosilink': 'ZosiLink',  # IOS
+    'com.ansjer.zosilink_a': 'ZosiLink',  # Android
+
+    'com.livecamera.cooperationh_a': 'PTC',  # Android
+
+    'WinUser': 'WinUser',  # windows
+    'MacUser': 'MacUser'   # mac
+
+}

+ 1 - 0
Ansjer/urls.py

@@ -205,6 +205,7 @@ urlpatterns = [
     path('Test', Test.Test.as_view()),
     # 微信绑定的用户获取验证码
     url(r'^oauth/authcode', UserController.OauthAuthCodeView.as_view()),
+    re_path(r'^single/login/(?P<operation>.*)$', UserController.SingleLoginView.as_view()),
     url(r'^oauth/perfect', UserController.OauthPerfectView.as_view()),
     url(r'^oauth/unbunding', UserController.UnbundingWXView.as_view()),
 

+ 279 - 1
Controller/UserController.py

@@ -26,7 +26,7 @@ from jwt.algorithms import RSAAlgorithm
 from ratelimit import limits
 
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, TUTK_PUSH_DOMAIN, \
-    LOGGER, CONFIG_US
+    LOGGER, CONFIG_US, APP_MAPPING, DETECT_PUSH_DOMAINS
 from Ansjer.config import BASE_DIR, CONFIG_EUR, CONFIG_INFO, SERVER_DOMAIN_EUR, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Controller.UserDevice.UserSubscriptionController import UserSubscriptionControllerView
@@ -3355,6 +3355,284 @@ 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:
+            token = request_dict.get('token', None)
+            tko = TokenObject(token)
+            if tko.code != 0:
+                return response.json(tko.code)
+            if operation == 'get-login-status':  # 获取登录状态
+                return self.get_login_status(response)
+            else:
+                return response.json(404)
+
+    @staticmethod
+    def get_login_status(response):
+        return response.json(0)
+
+    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)
+        # code_type = 1 表示修改绑定手机号
+        code_type = request_dict.get('code_type', None)
+        if email is not None:
+            email = email.strip()
+            # 阿里云的发送邮箱的调用方法
+            return self.get_aliyun_email_code(email, response)
+        elif phone is not None and code_type == "1":
+            phone = phone.strip()
+            country_code = str(country_code.strip())
+            return self.get_change_phone_code(country_code, phone, response, sign_name)
+        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()
+        key = email + '_SingleLogin'
+        identifying_code = reds.get_data(key=key)
+        # 是否以获取邮箱验证码
+        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=key, 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_151675019'
+            rec_phone = phone
+            if sign_name == 'zosi':
+                sign_ms = '周视'
+            else:
+                sign_ms = 'Ansjer'
+        else:
+            # 国际短信推送模板
+            temp_msg = 'SMS_172200051'
+            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)
+        app_bundle_id = request_dict.get('appBundleId', None)
+        token_val = request_dict.get('tokenVal', None)
+        if not all([app_bundle_id, token_val]):
+            return response.json(444, 'appBundleId,tokenVal')
+        new_bundle = APP_MAPPING.get(app_bundle_id, 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, new_bundle, token_val)
+        elif email is not None:
+            email = email.strip()
+            return self.do_email(email, authcode, password, response, password_version, salt, new_bundle, token_val)
+        else:
+            return response.json(444, 'phone')
+
+    @staticmethod
+    def do_email(email, authcode, password, response, password_version, salt, new_bundle, token_val):
+        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)
+        user_id = user_qs[0].userID
+        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, '删除缓存失败')
+        # key = 'token_user_{}_{}'.format(user_id, new_bundle)
+        # LOGGER.info('{}修改密码写入token:{}'.format(user_id, 'temp_value'))
+        # reds.set_data(key, 'temp_value')
+        # push_url = '{}transparent-transmission/logout-push'.format(DETECT_PUSH_DOMAINS)
+        # result = requests.post(push_url, data={'push_token': token_val, 'user_id': user_id,
+        #                                        'app_bundle_id': new_bundle})
+        # LOGGER.info('{}修改密码推送结果:{}'.format(user_id, result.json()))
+        return response.json(0)
+
+    @staticmethod
+    def do_phone(phone, authcode, password, response, password_version, salt, new_bundle, token_val):
+        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)
+        user_id = user_qs[0].userID
+        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, '删除缓存失败')
+        # key = 'token_user_{}_{}'.format(user_id, new_bundle)
+        # LOGGER.info('{}修改密码写入token:{}'.format(user_id, 'temp_value'))
+        # reds.set_data(key, 'temp_value')
+        # push_url = '{}transparent-transmission/logout-push'.format(DETECT_PUSH_DOMAINS)
+        # result = requests.post(push_url, data={'push_token': token_val, 'user_id': user_id,
+        #                                        'app_bundle_id': new_bundle})
+        # LOGGER.info('{}修改密码推送结果:{}'.format(user_id, result.json()))
+        return response.json(0)
+
+    @staticmethod
+    def get_change_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) + '_ChangePhone'
+        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)
+        identifying_code = RandomStr(6, True)
+        if country_code == '86':
+            # 国内短信推送模板
+            temp_msg = 'SMS_151675018'
+            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"])
+
+
 class UnbundingWXView(TemplateView):
 
     def get(self, request, *args, **kwargs):