我有一个基于挂架的web应用程序,通过
Sqlalchemy
(v0.5)到Postgres数据库。为了安全起见,我不使用普通的Postgres用户(例如“webapp”),而是要求用户输入自己的Postgres用户ID和密码,并使用它们建立连接,而不是遵循简单web应用程序的典型模式(正如在几乎所有教程中看到的那样)。这意味着我们可以充分享受Postgres安全性的好处。
更为复杂的是,有两个独立的数据库需要连接。尽管他们目前在同一个Postgres集群中,但他们需要能够在以后移动到不同的主机。
我们用的是sqlalchemy的
declarative
sqlalchemy的大多数示例都显示了一些琐碎的方法,例如在应用程序启动时使用通用数据库用户ID和密码设置元数据一次,这将通过web应用程序使用。这通常是通过Metadata.bind=create_engine()完成的,有时甚至是在数据库模型文件的模块级别。
我的问题是,我们如何推迟建立连接,直到用户登录,然后(当然)为每个后续请求重新使用这些连接,或者使用相同的凭据重新建立连接。
我们有这个工作,我们认为,但我不仅不能肯定它的安全性,我还认为它在这种情况下看起来非常重。
__call__
也许
即使任何给定的请求通常只引用一个或两个表,也不能在每个连接上引用。它看起来像这样:
# in lib/base.py on the BaseController class
def __call__(self, environ, start_response):
# note: web session contains {'username': XXX, 'password': YYY}
url1 = 'postgres://%(username)s:%(password)s@server1/finance' % session
url2 = 'postgres://%(username)s:%(password)s@server2/staff' % session
finance = create_engine(url1)
staff = create_engine(url2)
db_configure(staff, finance) # see below
... etc
# in another file
Session = scoped_session(sessionmaker())
def db_configure(staff, finance):
s = Session()
from db.finance import Employee, Customer, Invoice
for c in [
Employee,
Customer,
Invoice,
]:
s.bind_mapper(c, finance)
from db.staff import Project, Hour
for c in [
Project,
Hour,
]:
s.bind_mapper(c, staff)
s.close() # prevents leaking connections between sessions?
但是调用Session.bind_mapper()一次
桌上
每一个
显然,由于对强大安全性的渴望是所有这些的基础,我们不希望为高安全性用户建立的连接有任何可能会被低安全性用户在以后的请求中无意中使用。