U 更新ldap登录

pull/31/head
vapao 2020-03-09 12:56:00 +08:00
parent 6fb9430129
commit edad14e2c7
3 changed files with 40 additions and 92 deletions

View File

@ -11,7 +11,7 @@ class User(models.Model, ModelMixin):
username = models.CharField(max_length=100) username = models.CharField(max_length=100)
nickname = models.CharField(max_length=100) nickname = models.CharField(max_length=100)
password_hash = models.CharField(max_length=100) # hashed password 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_supper = models.BooleanField(default=False)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
access_token = models.CharField(max_length=32) access_token = models.CharField(max_length=32)

View File

@ -6,10 +6,10 @@ from django.views.generic import View
from django.db.models import F from django.db.models import F
from libs import JsonParser, Argument, human_datetime, json_response from libs import JsonParser, Argument, human_datetime, json_response
from apps.account.models import User, Role from apps.account.models import User, Role
from libs.ldap import LDAP
import time import time
import uuid import uuid
import json import json
from libs.ldap import LDAP
class UserView(View): class UserView(View):
@ -31,7 +31,6 @@ class UserView(View):
if error is None: if error is None:
form.password_hash = User.make_password(form.pop('password')) form.password_hash = User.make_password(form.pop('password'))
form.created_by = request.user form.created_by = request.user
form.type = '系统用户'
User.objects.create(**form) User.objects.create(**form)
return json_response(error=error) return json_response(error=error)
@ -140,80 +139,50 @@ def login(request):
Argument('type') Argument('type')
).parse(request.body) ).parse(request.body)
if error is None: 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': if form.type == 'ldap':
u = LDAP() ldap = LDAP()
valid = u.valid_user(form.username, form.password) is_success, message = ldap.valid_user(form.username, form.password)
if valid['status']: if is_success:
user = user.filter(type='LDAP').first() if not user:
if user: user = User.objects.create(username=form.username, nickname=form.username)
if not user.is_active: return handle_user_info(user, x_real_ip)
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'])
else: else:
user = user.filter(type='系统用户').first()
if user and user.deleted_by is None: if user and user.deleted_by is None:
if not user.is_active:
return json_response(error="账户已被系统禁用")
if user.verify_password(form.password): if user.verify_password(form.password):
cache.delete(form.username) return handle_user_info(user, x_real_ip)
x_real_ip = request.headers.get('x-real-ip', '')
ret = handle_user_info(user, form.username, x_real_ip)
return json_response(ret)
value = cache.get_or_set(form.username, 0, 86400) value = cache.get_or_set(form.username, 0, 86400)
if value >= 3: if value >= 3:
if user and user.is_active: if user and user.is_active:
user.is_active = False user.is_active = False
user.save() user.save()
return json_response(error='账户已被系统禁用') return json_response(error='账户已被系统禁用')
cache.set(form.username, value + 1, 86400) cache.set(form.username, value + 1, 86400)
return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用") return json_response(error="用户名或密码错误,连续多次错误账户将会被禁用")
return json_response(error=error)
def handle_user_info(user, username, x_real_ip): def handle_user_info(user, x_real_ip):
cache.delete(username) cache.delete(user.username)
token_isvalid = user.access_token and len(user.access_token) == 32 and user.token_expired >= time.time() 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.access_token = user.access_token if token_isvalid else uuid.uuid4().hex
user.token_expired = time.time() + 8 * 60 * 60 user.token_expired = time.time() + 8 * 60 * 60
user.last_login = human_datetime() user.last_login = human_datetime()
user.last_ip = x_real_ip user.last_ip = x_real_ip
user.save() user.save()
return { return json_response({
'access_token': user.access_token, 'access_token': user.access_token,
'nickname': user.nickname, 'nickname': user.nickname,
'is_supper': user.is_supper, 'is_supper': user.is_supper,
'has_real_ip': True if x_real_ip else False, 'has_real_ip': True if x_real_ip else False,
'permissions': [] if user.is_supper else user.page_perms 'permissions': [] if user.is_supper else user.page_perms
} })
def logout(request): def logout(request):
request.user.token_expired = 0 request.user.token_expired = 0
request.user.save() request.user.save()
return json_response() return json_response()

View File

@ -1,16 +1,14 @@
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug # Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
# Copyright: (c) <spug.dev@gmail.com> # Copyright: (c) <spug.dev@gmail.com>
# Released under the MIT License. # Released under the MIT License.
import ldap
from apps.setting.models import Setting from apps.setting.models import Setting
import ldap
import json import json
class LDAP: class LDAP:
def __init__(self): def __init__(self):
server_info = Setting.objects.exclude(key__in=('public_key', 'private_key')) \ server_info = Setting.objects.filter(key='ldap_service').first()
.filter(key='ldap_service').first()
ldap_info_dict = json.loads(server_info.value) ldap_info_dict = json.loads(server_info.value)
self.server = ldap_info_dict['server'] self.server = ldap_info_dict['server']
self.port = ldap_info_dict['port'] self.port = ldap_info_dict['port']
@ -18,37 +16,18 @@ class LDAP:
self.admin_dn = ldap_info_dict['admin_dn'] self.admin_dn = ldap_info_dict['admin_dn']
self.password = ldap_info_dict['password'] self.password = ldap_info_dict['password']
self.base_dn = ldap_info_dict['base_dn'] 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): def valid_user(self, username, password):
user = self.get_user_info(username) try:
if user['status']: conn = ldap.initialize("ldap://{0}:{1}".format(self.server, self.port), bytes_mode=False)
try: conn.simple_bind_s(self.admin_dn, self.password)
self.con.simple_bind_s(user['info'], password) search_filter = f'({self.rules}={username})'
return {'status': True, 'info': ''} ldap_result_id = conn.search(self.base_dn, ldap.SCOPE_SUBTREE, search_filter, None)
except Exception as error: result_type, result_data = conn.result(ldap_result_id, 0)
error = eval(str(error)) if result_type == ldap.RES_SEARCH_ENTRY:
return {'status': False, 'info': error['desc']} conn.simple_bind_s(result_data[0][0], password)
else: return True, None
return {'status': False, 'info': user['info']} else:
return False, 'LDAP用户未找到'
except Exception as error:
return False, '%s' % error