有没有办法以编程方式生成CouchDB cookie?
我正在开发一个应用程序,它将使用CouchDB为用户存储一些数据。 但我不希望用户直接登录到CouchDB。
我将有一个应用程序客户端(移动/网络),一个应用程序服务器和CouchDB服务器。 客户端应用程序将对应用程序服务器进行身份验证,然后myy理想的情况是我的应用程序服务器以编程方式对用户进行身份验证,然后将10分钟的cookie发送到客户端应用程序。
也就是说,我希望应用服务器代表应用客户端用户从CouchDB服务器请求Cookie,然后仅将Cookie发送给应用客户端。
应用程序服务器可以代表经过身份验证的用户发布到_session,但这需要:
出于安全原因,#3似乎是最好的,但这看起来像额外的工作,并且是对DB的额外往返(尽管并不是昂贵的)。 所以我的问题是:作为管理员,是否有任何方式代表用户生成cookie,而根本不使用用户的密码?
这也可能允许我完全拒绝来自我的应用程序服务器的对_session的请求,作为附加的安全措施。
为了完整起见,我还会提到我已经看过其他选项,并且发现他们想要:
代理身份验证
x_auth_token永不过期的事实令我感到担忧。 这意味着受到威胁的令牌将永久授予用户数据的访问权限。 而AFAICT,如果不更改用户名或服务器机密(这实际上也会使其他人的认证令牌无效)甚至无法使用令牌。 但也许我在这里错过了一些东西?
OAuth身份验证
这似乎只是解决了这个问题。 现在,不必将用户的密码存储在我的服务器应用程序中,我必须存储OAuth机密。 另外,现在我的服务器和客户端代码必须更复杂。
我不遵循你的确切目标。 您似乎暗示用户可能有密码(“应用服务器以编程方式对用户进行身份验证”),但您不希望用户“需要知道他们的CouchDB密码”。 你想要什么样的认证?
我已经采取了两种(一种)一般方法来对CouchDB进行身份验证:
“中间人”的方法,我在CouchDB之前拥有瘦中间件。 这个中间件将用户名/密码转发给“/ _session”,它会根据CouchDB _users数据库产生一个cookie或错误代码。 中间件将CouchDB中的这个cookie复制到自己的HTTP响应中(或者在错误的情况下显示一条消息)。 然后,在随后的需要数据库访问的请求中,它将Cookie(现在来自客户端请求)再次转发回数据库。
传统方法,您只需使用CouchDB作为数据存储并维护您自己的“用户”条目/索引。 确保您使用密码存储/处理的当前最佳做法,或使用为您处理这些细节的库。 中间件以“自己”的身份连接到数据库,并根据自己的会话处理使用自己的逻辑处理读/写权限。
或者 - 一种混合方式 - 您可以使用“/ _session”API来查看CouchDB是否接受用户名和密码。 如果有,请为该用户创建一个单独的中间件处理的会话。 (基本上,您只使用CouchDB的_user数据库作为“密码处理库”,其余的是传统方法,其中的访问控制在中间件而不是数据库中实现)。
对于现实生产中的东西,我倾向于只使用后两种(或者以前编号为1.5)... - 第一种方法很有趣,但CouchDB缺少文档级读取权限通常意味着给用户几乎直接访问数据库服务器在实践中是站不住脚的。
更新 :现在您的问题明确表明您希望客户端应用程序直接与两台服务器通话:应用程序(以前称为“中间件”)服务器和 CouchDB(数据库)服务器。 我将上面的内容留下,因为我认为它仍然有点用处,并为此更新提供了一些背景/上下文。
你怀疑代理认证是错误的解决方案,你是正确的:它不是为最终用户使用,而是真正取代上述#1的cookie转发“技巧”部分。 也就是说,代理认证是指当您完全信任一方(即您的中间件)提供代表用户的用户信息时。 但您希望用户直接与数据库交谈,并且您不能使用X-Auth-CouchDB-Token
信任他们。
我将根据您对OAuth选项的判断。 我认为它更接近你想要的,但很明显,你以不同的方式对用户进行了身份验证,并且不需要在CouchDB本身中存储每个用户的密钥。 OAuth 1.0所要求的请求签名确实意味着您需要在客户端应用程序的HTTP库中提供支持。
我看到了一些选项,没有构建自定义的CouchDB插件,这可以让您的应用服务器为您的数据库服务器将接受的经过身份验证的用户分发令牌:
代理毕竟! 也就是说,将数据库服务器隐藏在应用程序服务器或另一个轻量级定制反向代理之后。 所有这些中间件需要做的是检查你现有的客户端应用会话(cookie或其他认证头),如果有效,请设置CouchDB将接受的内部代理认证头 - 然后它逐字转发请求/响应的其余部分。
确定性密码,每用户,如果它让你感觉更好。 用一个只知道它的秘密配置你的应用程序服务器,然后将每个用户的密码设置为像HMAC(username, app_server_secret)
。 现在,当您想为用户生成令牌时,您的应用服务器可以基于每个用户生成密码。 请注意,这实际上并不比仅仅使用app_server_secret
作为每个用户的密码更安全 - CouchDB已经独立地对每个用户密码进行独立散列,因此如果有人获得了数据库的持有权,但不是您的应用程序的配置值,攻击者无法'把这两个分开。 在这两种情况下,防止未授权的数据库使用完全取决于保持app_server_secret
秘密。
重新实现CouchDB的当前Cookie生成算法。 CouchDB的cookie算法(查看源代码)基本上是data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret))
data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret))
。 其中secret
是couch_httpd_auth.secret
值加上用户的salt
值。 您可以将您的应用服务器的couchdb_httpd_auth / secret值告诉您的应用服务器,并且它可以按照相同的步骤生成您提供给客户端应用的有效Cookie,并且CouchDB将接受它作为自己的cookie。 此cookie将有效,直到时间戳+配置的couch_httpd_auth /超时。 尽管看起来像“hacky”,但这可能与您所要求的最接近,但您仍需要以某种方式设置/禁用用户的实际密码。
拓展natevw的辉煌答案。 我遇到了类似的问题,如果没有偶然发现答案,就不会意识到方案3是可能的。
这里是我的python3实现用于生成一个cookie(使用pycouchdb与沙发接口):
def generate_couchdb_cookie(couchAddress, couchSecret, username):
timestamp = format(int(time.time()), 'X')
data = username + ":" + timestamp
server = pycouchdb.Server(couchAddress)
db = server.database("_users")
doc = db.get("org.couchdb.user:" + username)
salt = doc["salt"]
secret = couchSecret + salt
hashed = hmac(secret.encode(), data.encode(), sha1).digest()
inbytes = data.encode() + ":".encode() + hashed
result = base64.urlsafe_b64encode(inbytes)
return "AuthSession=" + (result.decode("utf-8")).rstrip('=')
链接地址: http://www.djcxy.com/p/81147.html
上一篇: Is there any way to programmatically generate a CouchDB cookie?