python自动化运维学习第四十二天--cmdb权限相关代码实现
权限表中的to_display字段添加后,进入django的后台页面,把增删改权限的to_display项关联到查看,例如添加主机、编辑主机和删除主机的to_display字段选查看主机
查看的to_display项为空,不填。这样就把主机相关的菜单都放到查看主机这个菜单中了。主机、用户、菜单、权限等相关项都整合到查看项这个菜单中。
views.py中的登录相关代码
from demo import handler #导入handler模块
def login(request):
if request.method == "GET":
return render(request, "login.html")
user = request.POST.get("username", False)
pwd = request.POST.get("password", False)
# user_list = models.Users.objects.all()
if not user or not pwd:
error = "用户名或密码不能为空!"
return render(request, "login.html", locals())
else:
user_obj = models.Users.objects.filter(username=user, password=pwd)
if user_obj.first():
request.session['login'] = user_obj.first().username
handler.menu_handler(request, user_obj) #登录后处理菜单和权限相关数据
return redirect("/index/")
else:
error = "用户名或密码不正确,请重新输入!"
return render(request, "login.html", locals())
新建一个handler.py文件,把登录后菜单和权限相关数据做处理
from django.shortcuts import render,HttpResponse,redirect
def menu_handler(request, user_obj):
#把登录的用户相关的权限名字/url、显示的url/名字、权限组名、菜单名放到obj中,obj是QuerySet类型
obj = user_obj.values('position__auth__name',
'position__auth__url',
'position__auth__to_display__url',
'position__auth__to_display__name',
'position__auth__group__name',
'position__auth__group__title__title')
menu_dic = {}
for i in obj:
#把权限的url/name和显示的url/名字放到menu_auth_dic这个dict中
menu_auth_dic = {
'url': i.get('position__auth__url'),
'name': i.get('position__auth__name'),
'display_url': i.get('position__auth__to_display__url'),
'display_name': i.get('position__auth__to_display__name'),
}
if i.get('position__auth__group__title__title') in menu_dic.keys():
#如果菜单标题在menu_dic中执行
if not i.get('position__auth__to_display__name'): #如果是查看项
menu_dic[i.get('position__auth__group__title__title')]['lower'].append(menu_auth_dic) #menu_auth_dic字典添加到menu_dic字典的lower列表中
else:
menu_dic[i.get('position__auth__group__title__title')] = {}
menu_dic[i.get('position__auth__group__title__title')]['title'] = i.get('position__auth__group__title__title') #menu_dic字典的title列表赋值为菜单标题名
if not i.get('position__auth__to_display__name'): #如果为查看项
menu_dic[i.get('position__auth__group__title__title')]['lower'] = [menu_auth_dic, ] #menu_auth_dic字典赋值给menu_dic字典的lower列表
else:
menu_dic[i.get('position__auth__group__title__title')]['lower'] = [] #如果不是查看项则为空
#print('菜单---》', menu_dic)
request.session['menu_dict'] = menu_dic #菜单字典存到session表中
#权限相关和上边菜单相关差不多
auth_dic = {}
for i in obj:
if i.get('position__auth__group__name') in auth_dic.keys():
auth_dic[i.get('position__auth__group__name')]['url'].append(i.get('position__auth__url'))
else:
auth_dic[i.get('position__auth__group__name')] = {'url': [i.get('position__auth__url'), ], }
#print('权限---》', auth_dic)
request.session['auth_dict'] = auth_dic
配置urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.login),
url(r'^index/', views.index),
]
views.py中的index
def index(request):
menu_dict = request.session.get('menu_dict')
return render(request, 'index.html', locals())
index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<div id="index">
{% for item in menu_dict.values %}
<h2>{{ item.title }}</h2>
{% for i in item.lower %}
<a href="{{ i.url }}">{{ i.name }}</a>
{% endfor %}
{% endfor %}
</div>
</body>
</html>
显示效果如下
这是页面左侧菜单栏,不太好看,不过数据已经出来了。添加js效果,达到子菜单收到主菜单中,点击主菜单出现子菜单的效果。
菜单部分数据已经处理完成,下面是权限部分,权限的控制依靠用户获取的权限url,views.py中已经把权限相关的url组成的字典存放到session中了,通过这些url来达到限制用户访问的效果。如何通过这些url来限制用户权限,使用前边学的中间件,把这些url在中间件中做一个判断,如果匹配就跳转到指定url,不匹配就跳转到指定页面或者显示一些提示信息。
新建一个middleware目录,目录中创建一个中间件文件cmdb_auth.py,代码如下
import re
from django.shortcuts import render,redirect,HttpResponse
class MiddlewareMixin(object): #创建的中间件类
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
#白名单url
white_list = ["/login/", "/sign/", "/admin/*"]
class AuthMiddleware(MiddlewareMixin): #自定义一个类
def process_request(self, request):
# 获取当前请求的url
current_url = request.path_info
for url in white_list:
if re.match(url, current_url): #匹配白名单url
return None
# 获取session中保存当前用户的权限
auth_dict = request.session.get('auth_dict')
if not auth_dict:
return redirect('/login/') #没有登录跳转到登录页面
flag = False
for group_name, auth_url in auth_dict.items(): #循环权限字典中的key和value
for url in auth_url['url']:
regax = '^(0)$'.format(url) # 把url前边和后边添加“^”和“$”,表示开头和结尾
if re.match(regax, current_url): # 权限内的url匹配到当前访问的url
# 获取当前用户对当前组内的所有code,并赋值给request,稍后对这些数据做处理
request.permission_code_list = auth_url['url'] # 该url权限组内的所有url(如查看主机权限组内的添加、编辑和删除主机的url)
flag = True
break
if flag:
break
if not flag: #没有该url权限
return HttpResponse('没有权限')
在settings中配置好该中间件即可,当访问的url不在白名单中就会在走中间件对url做判断,当用户没有登录就会跳转到登录页面;当用户登录,请求url不在该用户权限内在提示,在权限内时继续往下执行代码,并会把该url权限组内的url存到request中,方便以后使用。
把代码整理下,配置相关代码可以移到setting中,方便查找修改。
这样基本完成了cmdb权限部分的功能。