• Django中的权限系统


    Django中已经为我们设置好了基本的权限系统,在定义好model同步数据库后,在每个库下面都会有一张 'auth_permission' 表。该表里面记录了每条权限的描述(name字段,can do something,会显示在后台付权限的列表中)和名字(codename字段,代码逻辑中检查权限使用,该字段会在权限验证函数perm_check中被 'request.user.has_perm' 方法调用,来判断是否通过验证。)

    权限系统的基本逻辑流程:

    • 1、用户发起操作请求时,根据url匹配到相应的试图函数处理(返回相关信息)
    • 2、在给用户返回信息之前,首先验证该用户是否有权限查看所请求的信息(装饰器)
    • 3、装饰器函数中,通过监测用户http请求的url、method和参数来确定权限
    • 4、若验证通过,返回查询信息(执行被装饰器装饰的函数)。若验证不通过,返回 403 页面

    1、在每个给前端返回信息的views函数上添加装饰器,

    from permissions import check_permission #导入方法
    
    @check_permission #向前段页面返回客户信息时,先执行装饰器方法,验证是否有权限
    def customer(request): ,,,

    @check_permission     
    def customer_info(request,customer_id):
      ,,,

    2、model中添加规则(数据库中添加权限纪录)

    class UserProfile(models.Model):
        user = models.OneToOneField(User)
        name = models.CharField(u"姓名",max_length=32)
        def __unicode__(self):
            return self.name
        class Meta:
            verbose_name_plural = u'用户信息'
    
            permissions = (                                        #可以在任一表中添加
                ('views_customer_list','显示列表信息'),
                ('views_customer_info','显示每条详细信息'),
                ('edit_views_culstomer_info','修改详细信息'),
            )

    修改了models.py文件后,需要同步到数据库。

    sudo python manage.py makemigrations
    
    sudo python manage.py migrate

    3、定义权限匹配方法

    appname/permission.py

    #!_*_ coding:utf-8 _*_

    from django.core.urlresolvers import resolve
    from django.shortcuts import render,redirect


    perm_dic ={
    'views_customer_list':['customer_list','GET',[]], #请求到达时,先匹配url,然后匹配请求方法,最后匹配参数,若都通过,则付给views_customer_list的权限
    'views_customer_info':['customer_info','GET',[]],
    'edit_views_customer_info':['customer_info','POST',['test']] #这里['test']可以随便填写
    }




    #不确定函数参数时,用 *args,**kwargs
    def perm_check(*args,**kwargs):
    request = args[0]
    #反向映射,将客户端请求的url转换为url别名,request.path_info为请求的完整url
    url_resovle_obj = resolve(request.path_info)
    #获取url别名
    current_url_namespace = url_resovle_obj.url_name
    #设置标示符,要匹配(循环)好多层时,可以先设置一个标示符,这里默认不匹配
    matched_flag = False
    matched_perm_key = None
    #如果存在url别名(url中必须有别名)
    if current_url_namespace is not None:
    #循环别名字典,取key值,即别名
    for perm_key in perm_dic:
    #字典里所有的值
    perm_val = perm_dic[perm_key]
    #格式必须为3个参数
    if len(perm_val) == 3:
    url_namespace,request_method,request_args = perm_val
    #先判断url是否匹配
    if url_namespace == current_url_namespace:
    #再判断请求方法是否匹配
    if request.method == request_method:
    #如果别名字典(perm_dic)中参数[]为空,则直匹配前两者即可
    if not request_args:
    #匹配成功
    matched_flag = True
    #将别名(字典key)付值给matched_perm_key
    matched_perm_key = perm_key
    #已匹配成功,退出循环
    break
    else: #字典中如果有参数,(参数可能有多个)
    #循环所有的参数
    for request_arg in request_args:
    #反射获取客户端请求的方法,这样就不用判断是get还是post了
    request_method_func = getattr(request,request_method)
    #如果请求的每个参数都能匹配成功
    if request_method_func.get(request_arg) is not None:
    matched_flag = True #匹配成功
    else:
    matched_flag = False
    break
    #如果全都匹配成功
    if matched_flag == True:
    matched_perm_key = perm_key
    break
    else:
    #如果没有进行权限匹配,则默认通过
    return True
    #如果权限匹配全部通过
    if matched_flag == True:
    #stu_crm.views_customer_list
    perm_str = "stu_crm.%s" %(matched_perm_key)
    #.has_perm()方法django自带,其参数为appname+auth_permission表中的codename字段,如果有此权限,则返回True
    if request.user.has_perm(perm_str):
    return True
    else:
    return False
    else:
    print("33[41;1m ----- no matched permission ----33[0m")


    def check_permission(func):
    def wrapper(*args,**kwargs):
    #如果没权限
    if not perm_check(*args,**kwargs):
    #args[0]即为request
    return render(args[0],'stu_crm/403.html')
    return func(*args,**kwargs)
    return wrapper
     

    4、修改customer.html,将固定的url用别名代替

    <td><a href="{% url 'customer_info' customer.id %}">{{ customer.id }}</a></td>

    5、修改url转发规则,加入别名

    appname/urls.py

    urlpatterns = [
        url(r'^$',views.dashboard),
        url(r'^customer/$',views.customer,name='customer_list'),
        url(r'^customer/(d+)/$',views.customer_info,name='customer_info'),    #必须添加url别名
    ]

    6、定义403页面。

    templates/403.html

    设置完毕后,使用超级用户登陆admin后台,在user中对每个普通用户设置权限。每添加一条权限,在表 'auth_user_user_permissions' 中就会记录一条。

    注:应首先使用超级用户将普通用户的'Staff status'选项选中,以便首先允许其登陆。

  • 相关阅读:
    MVC模式在Java Web应用程序中的实例分析
    MVC模式在Java Web应用程序中的实现
    设计模式简析
    《大型网站技术架构:核心原理与技术分析》5,6,7章简析
    spring引入HikariCP连接池
    sring引入mybatis
    spring中通过JNDI、DBCP、C3P0配置数据源
    springMVC框架搭建
    Timer定时执行
    SQL大杂烩
  • 原文地址:https://www.cnblogs.com/ahaii/p/5755718.html
Copyright © 2020-2023  润新知