V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
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
V2EX  ›  Python

在 django orm 里面加上权限控制

  •  
  •   chaleaoch · 2021-06-17 13:18:25 +08:00 · 1675 次点击
    这是一个创建于 1253 天前的主题,其中的信息可能已经有所发展或是发生改变。
    需求是这样的:
    我需要对一些资源(其实就是一些 model 表)的权限做一些限制.
    但是这些限制无法直接加在 api 上.
    譬如关联表啊 什么的. 需要考虑的情况比较复杂.


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

    自定义 当然没问题.

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


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


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

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

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

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

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

    2.重写 manage,至于操作函数也就那几个( filter, get, all, create, save, count ...) ,再底层可能有统一的入口函数,只能自己找找看
    Vegetable
        6
    Vegetable  
       2021-06-17 19:23:32 +08:00   ❤️ 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  
       2021-06-17 19:27:46 +08:00
    你好像还提到了读操作,读操作思路没研究过,不过读操作限制起来终究是简单一点,比如你可以在 model 的__init__阶段判断当前用户有没有权限获取这个实例,想读就一定需要实例化嘛。
    不过这种方式局限性也很大,还是得根据项目判断。
    lybcyd
        8
    lybcyd  
       2021-06-17 20:34:22 +08:00
    你的思路可以实现,自定义 manager 、queryset 和 model,覆盖 crud 方法就可以。或者用 signal 实现。注意自带的批量不会触发这些方法,所以要单独处理。

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

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

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

    需要判断的信息放进 context 带过去就试试;
    37Y37
        12
    37Y37  
       2021-06-18 10:37:14 +08:00
    换个思路,看看是否可以考虑根据 URL 来做权限控制?大概 6 年前写过一个简单的 demo 可以看看 https://gitee.com/ops-coffee/sadmin
    rationa1cuzz
        13
    rationa1cuzz  
       2021-06-18 14:13:31 +08:00
    重写或者封装 orm 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3638 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 00:53 · PVG 08:53 · LAX 16:53 · JFK 19:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.