我一直在尋找他們的維基上的sqlalchemy食譜,但不知道哪一個是最好實施我想要做的。預過濾用戶訪問sqlalchemy查詢的最佳方式是什麼?
我表格中的每一行都有一個與它關聯的user_id。現在,對於每個查詢,我都會查詢當前登錄的用戶的id,然後按照我感興趣的標準進行查詢。我擔心的是開發人員可能會忘記將此過濾器添加到查詢中(巨大的安全風險)。因此,我想根據當前用戶的管理權限設置一個全局過濾器來過濾登錄用戶可以看到的內容。
感謝您的幫助。謝謝。
我一直在尋找他們的維基上的sqlalchemy食譜,但不知道哪一個是最好實施我想要做的。預過濾用戶訪問sqlalchemy查詢的最佳方式是什麼?
我表格中的每一行都有一個與它關聯的user_id。現在,對於每個查詢,我都會查詢當前登錄的用戶的id,然後按照我感興趣的標準進行查詢。我擔心的是開發人員可能會忘記將此過濾器添加到查詢中(巨大的安全風險)。因此,我想根據當前用戶的管理權限設置一個全局過濾器來過濾登錄用戶可以看到的內容。
感謝您的幫助。謝謝。
下面是簡化的重定義查詢構造函數,用於過濾所有模型查詢(包括關係)。您可以將它傳遞給query_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.current_user
已存儲。
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)
我寫了一個SQLAlchemy的擴展,我覺得做你所描述的:https://github.com/mwhite/multialchemy
它通過進行代理更改Query._from_obj
和QueryContext._froms
性能,這哪裏是表,從最終獲取設置選擇執行此操作。
你有沒有想過使用數據庫安全系統來實現這一目標?例如,Oracle通過其VPD功能提供此功能(http://www.oracle.com/technology/deploy/security/database-security/virtual-private-database/index.html)。您也可以在其他數據庫中實現類似的功能(例如http://ddj.com/database/215900773和http://technet.microsoft.com/en-gb/library/cc966395.aspx)。只需谷歌「行級安全RDBSName」。 – stephan 2010-05-26 15:07:22
,或在所有添加適當限制的表上設置視圖或規則,並剝奪用戶直接讀取底層表的權限。 http://www.postgresql.org/docs/8.4/interactive/rules.html – 2010-09-23 21:42:54