在 django orm 里面加上权限控制 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
chaleaoch

在 django orm 里面加上权限控制

  •  
  •   chaleaoch Jun 17, 2021 2091 views
    This topic created in 1778 days ago, the information mentioned may be changed or developed.
    需求是这样的:
    我需要对一些资源(其实就是一些 model 表)的权限做一些限制.
    但是这些限制无法直接加在 api 上.
    譬如关联表啊 什么的. 需要考虑的情况比较复杂.


    所以我在想能不能 在 model 和 manager 上做文章. 譬如 model.objects.filter(**kwargs) 的时候报错 instance.save()的时候报错.

    自定义 当然没问题.

    我的问题是, 都有哪些 orm 的 api 会动表数据啊. 这就比较难受了. 不太好统计啊.


    各位大佬可有良策......


    谢谢大佬.
    13 replies    2021-06-18 14:13:31 +08:00
    chi1st
        1
    chi1st  
       Jun 17, 2021
    没完全理解你的意思,不知道 signal 能不能解决你的问题
    dayeye2006199
        2
    dayeye2006199  
       Jun 17, 2021
    看你要对 表 进行权限控制,还是对 行 进行控制。

    全面这个情况用 django 内置的 permission 体系就可以完成,can_view, can_edit, can_delete 之类的权限 associate 到用户身上就行了。

    后面这个情况没有开箱即用的方案,用的比较多的是这个第三方包: https://github.com/django-guardian/django-guardian
    wellsc
        3
    wellsc  
       Jun 17, 2021
    报错?报什么错?把客观原因找出来
    chaleaoch
        4
    chaleaoch  
    OP
       Jun 17, 2021
    @dayeye2006199 啊 我不是这个意思..

    你的方法是在应用层 每次对数据库进行操作之前先判断一下 是否有权限.

    我是想 不在应用层做, 就在 orm 里面把权限校验给做了.
    a719114136
        5
    a719114136  
       Jun 17, 2021
    1. 所有 db 操作通过函数封装一层,然后在函数里控制。

    2.重写 manage,至于操作函数也就那几个( filter, get, all, create, save, count ...) ,再底层可能有统一的入口函数,只能自己找找看
    Vegetable
        6
    Vegetable  
       Jun 17, 2021   1
    我也有一阵子没写 Django 了,不过还能扯两句。

    你的思路问题不大,因为动表的 api 真的很少。实例的 save 、delete,和 manager 的 delete 、bulk_create 、bulk_update 。
    https://docs.djangoproject.com/en/3.2/ref/models/querysets/

    前两个很好操作,你可以直接在 model 上修改,三年前我写过一篇相关的内容,不过当时是记录操作日志,不是权限控制 https://segmentfault.com/a/1190000015022691 当初也是年轻哈哈写的什么玩意

    manager 方法大部分会调用 model 的 save,但是批量操作的都不会,也就是 delete\bulk_create\bulk_update 。如果你想让别人用的爽一点,这里就得多做点工作。

    判断权限需要得到当前登录的用户,这一点其实挺烦的,Django 没有 flask 的 g,orm 层也没有请求上下文,你通过什么办法在 orm 层面得到请求上下文?这也是你需要解决的问题

    related: https://stackoverflow.com/questions/3227180/why-is-using-thread-locals-in-django-bad
    Vegetable
        7
    Vegetable  
       Jun 17, 2021
    你好像还提到了读操作,读操作思路没研究过,不过读操作限制起来终究是简单一点,比如你可以在 model 的__init__阶段判断当前用户有没有权限获取这个实例,想读就一定需要实例化嘛。
    不过这种方式局限性也很大,还是得根据项目判断。
    lybcyd
        8
    lybcyd  
       Jun 17, 2021
    你的思路可以实现,自定义 manager 、queryset 和 model,覆盖 crud 方法就可以。或者用 signal 实现。注意自带的批量不会触发这些方法,所以要单独处理。

    不过我觉得权限放在 orm 这层可能不是个好主意,以后修改维护都不太方便,orm 应该只关注查询,加太多功能就太臃肿了。为什么不能放在视图层?这个是最自然的解决方案,根据请求和 user 直接判断,也好维护。
    abersheeran
        9
    abersheeran  
       Jun 17, 2021   1
    显然,Django 的设计无法解决这个问题。权限跟用户有关系,用户只能从 request 对象拿。你用什么方式把 request 传进 ORM 里?
    chaleaoch
        10
    chaleaoch  
    OP
       Jun 17, 2021
    @lybcyd 因为我使用了大量的 viewset. 而权限控制是后加的功能.(之前是由 kong 来控制的)

    如果在 api 层(就是您说的视图层)控制,那有大量代码需要修改.
    另外 我这个项目业务逻辑很诡异. 在视图层做. 一不小心就容易出 bug.
    metamask
        11
    metamask  
       Jun 17, 2021
    感觉这么做的话,得重写方法,在里面再做一层定义,但应该是挺棘手的。

    比如上面说的 django-guardian,你模仿它的做法,然后在对应的 orm crud 方法,做一层判断;

    需要判断的信息放进 context 带过去就试试;
    37Y37
        12
    37Y37  
       Jun 18, 2021
    换个思路,看看是否可以考虑根据 URL 来做权限控制?大概 6 年前写过一个简单的 demo 可以看看 https://gitee.com/ops-coffee/sadmin
    rationa1cuzz
        13
    rationa1cuzz  
       Jun 18, 2021
    重写或者封装 orm 吧
    About     Help     Advertise     Blog     API     FAQ     Solana     5442 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 62ms UTC 07:41 PVG 15:41 LAX 00:41 JFK 03:41
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86