def get(self, request, *args, **kwargs): sso_code = request.GET.get('code') url = '{0}/accessToken?client_id={1}&client_secret={2}&redirect_uri={3}&code={4}&grant_type=authorization_code'.format( self.oauth_api, self.client_id, self.client_secret, self.redirect_uri, sso_code) _, token = HttpRequests().get(url) try: access_token = json.loads(token)['access_token'] _, user = HttpRequests().get('%s/profile?access_token=%s' % (self.oauth_api, access_token)) user_info = json.loads(user) user_id = user_info['id'] user_job_number = user_info['empid'] user_email = user_info['email'] user_name = user_info['name'] user_display = user_info['username'] import random password = "".join( random.sample( 'abcdefghijklmnopqrstuvwxyzAbcDfGijKnMnopqrStuvvxYZ0123456789', 8)) if not User.objects.filter(username=user_job_number).exists(): user = User() user.username = user_job_number user.password = make_password(password) user.password2 = cryptor.encrypt(password) user.display = user_display user.email = user_email user.save() try: # 添加到默认组,默认组设置最小权限 group = Group.objects.get(id=1) user.groups.add(group) except Exception: print('无id=1的权限组,无法默认添加') user = User.objects.get(username=user_job_number) # 调用django内置登录方法,防止管理后台二次登录 login(request, user) next_url = request.GET.get("next") if request.GET.get( "next", None) else reverse("accounts:profile") return HttpResponseRedirect(next_url) except: print(traceback.print_exc()) return render(request, 'login.html')
def login_authenticate(username, password): """登录认证,包含一个登录失败计数器,5分钟内连续失败5次的账号,会被锁定5分钟""" sys_config = SysConfig().sys_config if sys_config.get('lock_cnt_threshold'): lock_cnt_threshold = int(sys_config.get('lock_cnt_threshold')) else: lock_cnt_threshold = 5 if sys_config.get('lock_time_threshold'): lock_time_threshold = int(sys_config.get('lock_time_threshold')) else: lock_time_threshold = 300 # 服务端二次验证参数 if username == "" or password == "" or username is None or password is None: result = {'status': 2, 'errmsg': '用户名或密码为空,请重新输入!'} elif username in login_failure_counter and login_failure_counter[username]["cnt"] >= lock_cnt_threshold and ( datetime.datetime.now() - login_failure_counter[username]["last_failure_time"]).seconds \ <= lock_time_threshold: result = {'status': 3, 'errmsg': '登录失败超过5次,该账号已被锁定5分钟!'} else: if username == 'admin': # 调用 django 认证系统 user = authenticate(username=username, password=password) else: # 调用 Bim 统一身份认证系统 # {"token":{"tokenId":"......"},"roles":[],"attributes":[{"values":["WD44134"],"name":"uid"}]} # {"exception":{"message":"密码无效","name":"com.bamboocloud.bam.idsvcs.InvalidPassword"}} # {"exception":{"message":"验证失败","name":"com.bamboocloud.bam.idsvcs.InvalidCredentials"}} url = 'http://bam.yadoom.com:8080/bam/identity/json/authenticateapi' data = { 'uid': username, 'usercredential': password, 'app_id': 'oa', 'app_key': 'password', 'attributenames': 'uid', 'uri': 'realm=/', 'module': 'LDAP' } _, ret = HttpRequests().post(url, data) ret = json.loads(ret) print(ret) if 'exception' not in ret: # 认证成功 url = 'http://bam.yadoom.com:8080/bam/identity/json/attributesapi' data = { 'tokenid': ret['token']['tokenId'], 'app_id': 'oa', 'app_key': 'password' } _, ret = HttpRequests().post(url, data) ret = json.loads(ret) display = '' if 'exception' not in ret: for item in ret['attributes']: if item['name'] == 'sn': display = item['values'][0] if not User.objects.filter(username=username).exists(): user = User() user.username = username user.display = display user.password = make_password(password) user.password2 = cryptor.encrypt(password) user.save() try: # 添加到默认组,默认组设置最小权限 group = Group.objects.get(id=1) user.groups.add(group) except Exception: print('无id=1的权限组,无法默认添加') else: user = User.objects.get(username=username) if user.password != make_password(password): user.password = make_password(password) user.password2 = cryptor.encrypt(password) user.save(update_fields=['password']) if display and user.display != display: user.display = display user.save(update_fields=['display']) user = User.objects.get(username=username) else: user = None if user: # 登录成功 # 获取该用户的钉钉 userid,用于给他发钉钉消息 if sys_config.get( "ding_to_person") == 'true' and username != 'admin': get_ding_user_id(username) # 如果登录失败计数器中存在该用户名,则清除之 if username in login_failure_counter: login_failure_counter.pop(username) result = {'status': 0, 'result': 'Successful'} else: # 登录失败 if username not in login_failure_counter: # 第一次登录失败,登录失败计数器中不存在该用户,则创建一个该用户的计数器 login_failure_counter[username] = { "cnt": 1, "last_failure_time": datetime.datetime.now() } else: if (datetime.datetime.now() - login_failure_counter[username]["last_failure_time"] ).seconds <= lock_time_threshold: login_failure_counter[username]["cnt"] += 1 else: # 上一次登录失败时间早于5分钟前,则重新计数。以达到超过5分钟自动解锁的目的。 login_failure_counter[username]["cnt"] = 1 login_failure_counter[username][ "last_failure_time"] = datetime.datetime.now() result = {'status': 1, 'errmsg': '用户名或密码错误,请重新输入!'} return result