Filter 对于sqlalchemy查询,预筛选用户访问权限的最佳方法是什么?

Filter 对于sqlalchemy查询,预筛选用户访问权限的最佳方法是什么?,filter,sqlalchemy,acl,Filter,Sqlalchemy,Acl,我一直在看他们维基上的sqlalchemy食谱,但不知道哪一个最适合实现我要做的 “我的表”中的每一行都有一个与之关联的用户id。现在,对于每个查询,我都按照当前登录用户的id进行查询,然后按照我感兴趣的条件进行查询。我担心的是,开发人员可能会忘记将此过滤器添加到查询中(这是一个巨大的安全风险)。因此,我想根据当前用户的管理权限设置一个全局过滤器,以过滤登录用户可以看到的内容 谢谢你的帮助。谢谢。下面是简化的重新定义的查询构造函数,用于过滤所有模型查询(包括关系)。您可以将其作为query\u

我一直在看他们维基上的sqlalchemy食谱,但不知道哪一个最适合实现我要做的

“我的表”中的每一行都有一个与之关联的用户id。现在,对于每个查询,我都按照当前登录用户的id进行查询,然后按照我感兴趣的条件进行查询。我担心的是,开发人员可能会忘记将此过滤器添加到查询中(这是一个巨大的安全风险)。因此,我想根据当前用户的管理权限设置一个全局过滤器,以过滤登录用户可以看到的内容


谢谢你的帮助。谢谢。

下面是简化的重新定义的查询构造函数,用于过滤所有模型查询(包括关系)。您可以将其作为
query\u cls
参数传递给
sessionmaker
。用户ID参数不需要是全局的,只要会话是在它已经可用的情况下构造的

class HackedQuery(Query):

    def get(self, ident):
        # Use default implementation when there is no condition
        if not self._criterion:
            return Query.get(self, ident)
        # Copied from Query implementation with some changes.
        if hasattr(ident, '__composite_values__'):
            ident = ident.__composite_values__()
        mapper = self._only_mapper_zero(
                    "get() can only be used against a single mapped class.")
        key = mapper.identity_key_from_primary_key(ident)
        if ident is None:
            if key is not None:
                ident = key[1]
        else:
            from sqlalchemy import util
            ident = util.to_list(ident)
        if ident is not None:
            columns = list(mapper.primary_key)
            if len(columns)!=len(ident):
                raise TypeError("Number of values doen't match number "
                                'of columns in primary key')
            params = {}
            for column, value in zip(columns, ident):
                params[column.key] = value
            return self.filter_by(**params).first()


def QueryPublic(entities, session=None):
    # It's not directly related to the problem, but is useful too.
    query = HackedQuery(entities, session).with_polymorphic('*')
    # Version for several entities needs thorough testing, so we 
    # don't use it yet.
    assert len(entities)==1, entities
    cls = _class_to_mapper(entities[0]).class_
    public_condition = getattr(cls, 'public_condition', None)
    if public_condition is not None:
        query = query.filter(public_condition)
    return query
它只适用于单模型查询,要使它适用于其他情况,需要做大量的工作。我希望看到一个详细的版本,因为它必须具有大多数web应用程序的功能。它使用存储在每个模型类中的固定条件,因此您必须根据自己的需要对其进行修改。

这里是一个非常简单的实现,它假设存在属性/属性
self。当前\u用户
登录的用户已存储

class YourBaseRequestHandler(object):

    @property
    def current_user(self):
        """The current user logged in."""
        pass

    def query(self, session, entities):
        """Use this method instead of :method:`Session.query()
        <sqlalchemy.orm.session.Session.query>`.

        """
        return session.query(entities).filter_by(user_id=self.current_user.id)
class YourBaseRequestHandler(对象):
@财产
def当前用户(自身):
“”“当前用户已登录。”“”
通过
def查询(自身、会话、实体):
“”“使用此方法而不是:方法:`Session.query()
`.
"""
return session.query(entities).filter\u by(user\u id=self.current\u user.id)

我编写了一个SQLAlchemy扩展,我认为它符合您的描述:


它通过代理对
查询所做的更改来实现这一点。这些更改来自\u obj
QueryContext.\u来自属性,这些属性是要从中选择的表的最终设置位置。

您是否考虑过使用数据库安全系统来实现这一点?例如,Oracle通过其VPD功能()提供此功能。您也可以在其他数据库中实现类似的功能(例如和)。只需在谷歌上搜索“行级安全RDBSName”,或者在所有表上设置视图或规则,添加适当的限制,并剥夺用户直接读取底层表的能力。因此,我最终以以下几个方面的组合来遵循你的答案。有没有一种方法可以将模型类级别的查询指定为sessionmaker的假设?并非所有的模型都有我想要筛选的列。哦,我在模型中确实使用了query=Session.query\u属性(FilterByUserQuery)。非常感谢。