通用权限系统

前言:

权限是什么?

对于web程序来说,一条权限 = 一个动作 =一个url + 一种请求方法(get/post/put...) + 若干个请求参数(?name="name"&sex=1&age=10 ...)

用户访问的每个不同的 fullpath就决定了用户能获取到什么;通过区分fullpath就可以做到web程序的权限控制;

 

 

一、Django的auth_permission表

Django程序在migrate数据库之后,会自动生成一张auth_permission表,这张表专门用户存储用户权限信息;

 

那么如何在这张表里新增权限记录呢?

在model.py的任何一张表下增加class Meta:

class Customer(models.Model):
    '''
    客户信息表
     '''
    date=models.DateTimeField(auto_now_add=True,verbose_name='合作时间')
    name = models.CharField(max_length=266, verbose_name='客户姓名')
    customer_detail=models.ForeignKey('CustomerDetail',verbose_name='客户详细信息')
    def __str__(self):
        return self.name

    class Meta:  # 用户和用户所有的权限,通过Django admin的user表关联起来!
        permissions = (
                   #权限名称                 #权限描述!
            ('view_customer_list', '可以查看客户列表1111'),
            ('view_customer_info', '可查看用客户详细信息11111'),
            ('edit_own_customer_info', '可以删除客户信息111111'),)
扩展auth_permission表

 

 

 

二、Django admin 让权限关联上用户

 

1.auth_permission表和admin自带的auth_group、user表是M2M关系,

 

 

2.所以就可以通过Django admin直接给 用户/用户组 添加权限了;

 

 

 2.给用户关联权限成功之后,user对象的has_perm()就可以去检测该用户 否拥有某个权限?

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "permission_system.settings")
import django
django.setup()

from app01 import models


user_obj=models.UserInfo.objects.all()[1]
print(user_obj) #注意superuser 拥有任何权限,必须是普通用户调用 has_perm()
print(user_obj.has_perm('app01.view_customer_list')) #True
user.has_perm(“app名.权限名”)

 

 

 

三、数据结构设计,让用户权限名 关联上Django的每个url;

通过以上步骤   

每个用户仅仅是和权限名称关联了起来,但是真正的权限是url啊!但url又不是固定的;

所以得 自己设计数据结构 让 用户权限名 关联上url别名;(url别名具有固定标识作用)

 

perm_dic = {
    # auth_permissions表权限    url的别名    请求方法  携带参数?name='2GO' 
    'view_customer_list': ['customer_list','GET',[]],
    'view_customer_info': ['customer_detail','GET',[]],
    'edit_own_customer_info': ['customer_detail','POST',['qq','nam']],
}

 

 

 

四、通过给视图函数增加装饰器验证用户是否  拥有访问权限?

让 每个url、url请求方式、?=携带参数,(完整URL) 和用户权限关联之后,就可以在用户访问Django程序的时候,

抓取到 request.path_info、request.method、request.GET/POST.get(‘args’) 和自己设计好的 数据结构去math了;

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Alex Li
from django.core.urlresolvers import resolve
from django.shortcuts import render
perm_dic = {
    'view_customer_list': ['customer_list','GET',[]],
    'view_customer_info': ['customer_detail','GET',[]],
    'edit_own_customer_info': ['customer_detail','POST',['qq','nam']],
}

def perm_check(*args,**kwargs):
    request = args[0]
    url_resovle_obj = resolve(request.path_info)
    current_url_namespace = url_resovle_obj.url_name
    #app_name = url_resovle_obj.app_name #use this name later
    print("url namespace:",current_url_namespace)
    matched_flag = False # find matched perm item
    matched_perm_key = None
    if current_url_namespace is not None:#if didn't set the url namespace, permission doesn't work
        print("find perm...")
        for perm_key in perm_dic:
            perm_val = perm_dic[perm_key]
            if len(perm_val) == 3:#otherwise invalid perm data format
                url_namespace,request_method,request_args = perm_val
                print(url_namespace,current_url_namespace)
                if url_namespace == current_url_namespace: #matched the url
                    if request.method == request_method:#matched request method
                        if not request_args:#if empty , pass
                            matched_flag = True
                            matched_perm_key = perm_key
                            print('mtched...')
                            break #no need looking for  other perms
                        else:
                            for request_arg in request_args: #might has many args
                                request_method_func = getattr(request,request_method) #get or post mostly
                                #print("----->>>",request_method_func.get(request_arg))
                                if request_method_func.get(request_arg) is not None:
                                    matched_flag = True # the arg in set in perm item must be provided in request data
                                else:
                                    matched_flag = False
                                    print("request arg [%s] not matched" % request_arg)
                                    break #no need go further
                            if matched_flag == True: # means passed permission check ,no need check others
                                print("--passed permission check--")
                                matched_perm_key = perm_key
                                break

    else:#permission doesn't work
        return True

    if matched_flag == True:
        #pass permission check
        perm_str = "app01.%s" %(matched_perm_key) #crm.view_customer_list
        if request.user.has_perm(perm_str):
            print("\033[42;1m--------passed permission check----\033[0m")
            return True
        else:
            print("\033[41;1m ----- no permission ----\033[0m")
            print(request.user,perm_str)
            return False
    else:
        print("\033[41;1m ----- no matched permission  ----\033[0m")


def check_permission(func):
    def wrapper(*args,**kwargs):
        print('---start check perm---')
        if perm_check(*args,**kwargs) is not True:#no permisssion
            return render(args[0],'403.html')
        return func(*args,**kwargs)
    return  wrapper
permisssion.py

 

 

 

五、权限插件和视图的无缝对接

权限插件完成之后,如何在不修改代码的前提下,通用得 结合到每个项目中呢?使用装饰器;

from django.shortcuts import render,HttpResponse,redirect
from app01 import models
from app01.permission import check_permission
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt


def acc_login(request):
    error = ''
    if request.method == "POST":
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(username=username,password=password)
        if user:
            login(request, user)
            return  redirect('/index/')
        else:
            error = "Wrong username or password!"
    return render(request,'login.html',{'error':error })

@login_required
def index(request):
    return render(request,'index.html')


@login_required
@check_permission
def customer_list(request):
    return render(request,'customer_list.html')

@login_required
@check_permission
def customer_detail(request):
    return render(request,'customer_detail.html')
views.py

 

 

六、权限极致到按钮

如果权限精细到1个URL我感觉还是不够,还可以精细到 1个URL返回的标签;

    def process_response(self, request, response):
        if request.path_info =='/arya/cmdb/worker_order/':
            BS=BeautifulSoup(response.content,"html5lib")
            tags=BS.find_all(class_='btn')
            for tag in tags:
                tag.decompose()
            response.content=str(BS)
        return response
中间件+BeautifulSoup过滤
   def process_response(self, request, response):
        #返回相关子工单、父工单返回逻辑
        if request.path_info == '/arya/cmdb/worker_order/':
            current_list_url = '/arya/cmdb/worker_order/'
            curent_page=request.GET.get('page','1')
            request.session['curent_page']=curent_page

        if request.path_info == '/arya/cmdb/worker_order/see/':
            current_see_url = '/arya/cmdb/worker_order/see/'
            BS = BeautifulSoup(response.content,"html5lib")
            current_obj=models.Worker_order.objects.get(pk=request.GET.get('id'))
            if current_obj.parent:#子工单
                go_back_url=current_see_url+'?id='+str(current_obj.parent.pk)
            else:#就是父工单
                page_number=request.session['curent_page']
                go_back_url ='/arya/cmdb/worker_order/?page=' + str(page_number)

            BS.find(id='go_back').attrs['href'] = go_back_url

            response.content = str(BS)
        return response
返回按钮

 

 

 

 

 

参考:

https://www.cnblogs.com/alex3714/articles/6661911.html

 

转载于:https://www.cnblogs.com/sss4/p/9364399.html

通用权限管理框架源码 2013-5-15更新功能: 1、菜单导航管理 2、操作按钮 3、角色管理 4、部门管理 5、用户管理(用户权限) 6、用户组管理(设置成员,用户组权限) 7、系统配置(动态配置系统参数) 8、附加属性(自定义属性) 9、系统日志(异常记录) 10、数据库备份/还原 11、资源管理,(动态数据库) 12、个人信息(基本信息,附加信息,用户角色,拥有权限) 13、首页快捷 14、数据回收站(业务功能删除过数据,全部保留在回收站) 15、系统个性化设置(切换菜单导航) 2012-9-10更新内容: 系统UI,给人感觉非常好,体积小巧,速度快 该源码是适用用于应用系统后台模块的管理(可扩展至支持集中化的权限管理平台), 0.支持N级菜单导航,菜单显示方式支持目前支持2种模式分别:菜单(无限级),横向(2级) 1.动态切换皮肤,目前有两狂UI 蓝色,咖啡色 2.表单验证,文本框高亮起来 3.可以动态分配权限按钮,分配角色权限,目录结构,栏目的链接都可以修改。权限管理非常灵活, 4.可以隐藏左侧导航栏,打开左侧导航栏,默认是打开,table表格都自应大小的 5.动态创建数据表,删除用户表,点击数据 表 可以查询字段信息 6.可以直接执行sql脚本 7.兼容 IE6,7,8,9 /Firefox /Google Chrome 这些浏览器都测试过 8.批量删除,自定义复选框样式,可以全选/反选 9.角色分级,集团和分公司的关系 10.权限 横向就是业务部分,具体负责哪块业务,纵向是级别 11.动态报表设置,并且可以导出Excel 12.登陆日记,操作日记,异常日记 13.海量批量删除数据库,调用公共存储过程,参数,表明,主键 特点: UI:传统html css,美观 漂亮 大方 实用 js框架:jquery 系统大部分使用AJAX操作。大大提高了用户体验 功能描述: 1.支持N级菜单导航,菜单显示方式支持目前支持2种模式分别: 菜单(无限级),横向(2级) 2.表单验证,文本框高亮起来 3.可以动态分配权限按钮,分配角色权限,目录结构,栏目的链接都可以修改。 4.可以隐藏左侧导航栏,打开左侧导航栏,默认是打开,table表格都自应大小的 5.动态创建数据表,删除用户表,点击数据 表 可以查询字段信息 6.可以直接执行sql脚本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值