前言:
权限是什么?
对于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'),)
二、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
三、数据结构设计,让用户权限名 关联上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("