From edad14e2c7e547eb568db12a3e38882e759fd6b7 Mon Sep 17 00:00:00 2001 From: vapao Date: Mon, 9 Mar 2020 12:56:00 +0800 Subject: [PATCH] =?UTF-8?q?U=20=E6=9B=B4=E6=96=B0ldap=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spug_api/apps/account/models.py | 2 +- spug_api/apps/account/views.py | 79 ++++++++++----------------------- spug_api/libs/ldap.py | 51 +++++++-------------- 3 files changed, 40 insertions(+), 92 deletions(-) diff --git a/spug_api/apps/account/models.py b/spug_api/apps/account/models.py index 543b74e..281e344 100644 --- a/spug_api/apps/account/models.py +++ b/spug_api/apps/account/models.py @@ -11,7 +11,7 @@ class User(models.Model, ModelMixin): username = models.CharField(max_length=100) nickname = models.CharField(max_length=100) password_hash = models.CharField(max_length=100) # hashed password - type = models.CharField(max_length=20, default='系统用户') + type = models.CharField(max_length=20, default='default') is_supper = models.BooleanField(default=False) is_active = models.BooleanField(default=True) access_token = models.CharField(max_length=32) diff --git a/spug_api/apps/account/views.py b/spug_api/apps/account/views.py index 88e6b60..a5d7988 100644 --- a/spug_api/apps/account/views.py +++ b/spug_api/apps/account/views.py @@ -6,10 +6,10 @@ from django.views.generic import View from django.db.models import F from libs import JsonParser, Argument, human_datetime, json_response from apps.account.models import User, Role +from libs.ldap import LDAP import time import uuid import json -from libs.ldap import LDAP class UserView(View): @@ -31,7 +31,6 @@ class UserView(View): if error is None: form.password_hash = User.make_password(form.pop('password')) form.created_by = request.user - form.type = '系统用户' User.objects.create(**form) return json_response(error=error) @@ -140,80 +139,50 @@ def login(request): Argument('type') ).parse(request.body) if error is None: - user = User.objects.filter(username=form.username) + x_real_ip = request.headers.get('x-real-ip', '') + user = User.objects.filter(username=form.username, type=form.type).first() + if user and not user.is_active: + return json_response(error="账户已被系统禁用") if form.type == 'ldap': - u = LDAP() - valid = u.valid_user(form.username, form.password) - if valid['status']: - user = user.filter(type='LDAP').first() - if user: - if not user.is_active: - return json_response(error="账户已被系统禁用") - if not user.role_id: - return json_response(error="LDAP用户角色未分配") - - x_real_ip = request.headers.get('x-real-ip', '') - ret = handle_user_info(user, form.username, x_real_ip) - return json_response(ret) - - x_real_ip = request.headers.get('x-real-ip', '') - form.access_token = uuid.uuid4().hex - form.nickname = form.username - form.token_expired = time.time() + 8 * 60 * 60 - form.last_login = human_datetime() - form.last_ip = x_real_ip - form.type = 'LDAP' - form.pop('password') - User.objects.create(**form) - return json_response({ - 'access_token': form.access_token, - 'nickname': form.username, - 'is_supper': False, - 'has_real_ip': True if x_real_ip else False, - 'permissions': [] - }) - return json_response(error=valid['info']) + ldap = LDAP() + is_success, message = ldap.valid_user(form.username, form.password) + if is_success: + if not user: + user = User.objects.create(username=form.username, nickname=form.username) + return handle_user_info(user, x_real_ip) else: - user = user.filter(type='系统用户').first() if user and user.deleted_by is None: - if not user.is_active: - return json_response(error="账户已被系统禁用") if user.verify_password(form.password): - cache.delete(form.username) - x_real_ip = request.headers.get('x-real-ip', '') - ret = handle_user_info(user, form.username, x_real_ip) - return json_response(ret) + return handle_user_info(user, x_real_ip) - value = cache.get_or_set(form.username, 0, 86400) - if value >= 3: - if user and user.is_active: - user.is_active = False - user.save() - return json_response(error='账户已被系统禁用') - cache.set(form.username, value + 1, 86400) - return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用") - return json_response(error=error) + value = cache.get_or_set(form.username, 0, 86400) + if value >= 3: + if user and user.is_active: + user.is_active = False + user.save() + return json_response(error='账户已被系统禁用') + cache.set(form.username, value + 1, 86400) + return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用") -def handle_user_info(user, username, x_real_ip): - cache.delete(username) +def handle_user_info(user, x_real_ip): + cache.delete(user.username) token_isvalid = user.access_token and len(user.access_token) == 32 and user.token_expired >= time.time() user.access_token = user.access_token if token_isvalid else uuid.uuid4().hex user.token_expired = time.time() + 8 * 60 * 60 user.last_login = human_datetime() user.last_ip = x_real_ip user.save() - return { + return json_response({ 'access_token': user.access_token, 'nickname': user.nickname, 'is_supper': user.is_supper, 'has_real_ip': True if x_real_ip else False, 'permissions': [] if user.is_supper else user.page_perms - } + }) def logout(request): request.user.token_expired = 0 request.user.save() return json_response() - diff --git a/spug_api/libs/ldap.py b/spug_api/libs/ldap.py index a641727..3e748ce 100644 --- a/spug_api/libs/ldap.py +++ b/spug_api/libs/ldap.py @@ -1,16 +1,14 @@ # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) # Released under the MIT License. - -import ldap from apps.setting.models import Setting +import ldap import json class LDAP: def __init__(self): - server_info = Setting.objects.exclude(key__in=('public_key', 'private_key')) \ - .filter(key='ldap_service').first() + server_info = Setting.objects.filter(key='ldap_service').first() ldap_info_dict = json.loads(server_info.value) self.server = ldap_info_dict['server'] self.port = ldap_info_dict['port'] @@ -18,37 +16,18 @@ class LDAP: self.admin_dn = ldap_info_dict['admin_dn'] self.password = ldap_info_dict['password'] self.base_dn = ldap_info_dict['base_dn'] - self.con = ldap.initialize("ldap://{0}:{1}".format(self.server, self.port), bytes_mode=False) - try: - self.con.simple_bind_s(self.admin_dn, self.password) - except Exception as error: - self.error = error - - def get_user_info(self, username): - try: - search_scope = ldap.SCOPE_SUBTREE - search_filter_name = self.rules - retrieve_attributes = None - search_filter = '(' + search_filter_name + "=" + username + ')' - ldap_result_id = self.con.search(self.base_dn, search_scope, search_filter, retrieve_attributes) - result_type, result_data = self.con.result(ldap_result_id, 0) - if result_type == ldap.RES_SEARCH_ENTRY: - return {'status': True, 'info': result_data[0][0]} - else: - return {'status': False, 'info': 'LDAP用户未找到'} - except Exception as error: - error = eval(str(error)) - return {'status': False, 'info': error['desc']} def valid_user(self, username, password): - user = self.get_user_info(username) - if user['status']: - try: - self.con.simple_bind_s(user['info'], password) - return {'status': True, 'info': ''} - except Exception as error: - error = eval(str(error)) - return {'status': False, 'info': error['desc']} - else: - return {'status': False, 'info': user['info']} - + try: + conn = ldap.initialize("ldap://{0}:{1}".format(self.server, self.port), bytes_mode=False) + conn.simple_bind_s(self.admin_dn, self.password) + search_filter = f'({self.rules}={username})' + ldap_result_id = conn.search(self.base_dn, ldap.SCOPE_SUBTREE, search_filter, None) + result_type, result_data = conn.result(ldap_result_id, 0) + if result_type == ldap.RES_SEARCH_ENTRY: + conn.simple_bind_s(result_data[0][0], password) + return True, None + else: + return False, 'LDAP用户未找到' + except Exception as error: + return False, '%s' % error