有什么办法以编程方式生成CouchDB cookie? [英] Is there any way to programmatically generate a CouchDB cookie?

查看:72
本文介绍了有什么办法以编程方式生成CouchDB cookie?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个将使用CouchDB为用户存储一些数据的应用程序.但是我不希望用户直接登录CouchDB.

I'm working on an app which will use CouchDB to store some data for users. But I don't want users to log into CouchDB directly.

我将拥有一个应用程序客户端(移动/网络),一个应用程序服务器和CouchDB服务器.客户端应用程序将向应用服务器进行身份验证,然后,最理想的情况是我的应用服务器以编程方式对用户进行身份验证,然后仅将10分钟的Cookie发送到客户端应用.

I will have an app client (mobile/web), an app server, and the CouchDB server. The client app will authenticate to the app server, then myy ideal scenario would be for my app server to authenticate the users programmatically, then send just the 10-minute cookie to the client app.

也就是说,我希望应用程序服务器代表应用程序客户端的用户向CouchDB服务器请求Cookie,然后仅将cookie发送给应用程序客户端.

That is, I would like the app server to request a Cookie from the CouchDB server on behalf of the user of the app client, then send only the cookie to the app client.

应用服务器可以仅代表已认证的用户POST到_session,但这需要:

The app server could just POST to _session on behalf of the authenticated user, but this requires:

  1. 在应用服务器中维护用户密码列表
  2. 为所有用户使用一个已知的密码
  3. 将每个身份验证请求的密码重置为随机值

出于安全考虑,#3似乎是最好的选择,但这似乎是额外的工作,并且是DB的额外往返行程(尽管这不是昂贵的行程).所以我的问题是:作为管理员,有没有什么方法可以代表用户生成Cookie,而根本不使用用户密码?

For security reasons, #3 seems the best, but this seems like extra work, and is an extra round-trip to the DB (albeit, not an expensive one). So my question is: Is there any, as an administrator, way to generate a cookie on behalf of a user, without using the users' password at all?

作为一种附加的安全措施,这可能还允许我完全拒绝对_session的请求(除了我的应用服务器之外).

This would also potentially allow me to entirely reject requests to _session except from my app server, as an added security measure.

为了完整起见,我还要提到我已经查看了这些其他选项,并发现它们有需求:

And for the sake of completeness, I'll also mention that I've looked at these other options, and found them wanting:

  1. 代理身份验证

x_auth_token 永不过期的事实是我很担心这意味着泄露的令牌将永久授予对用户数据的访问权限.而对于AFAICT,即使不更改用户名或服务器机密也无法使令牌无效(这实际上也会使其他所有人的身份验证令牌无效).但是也许我在这里错过了什么?

The fact that the x_auth_token never expires is worrisome to me. It means a compromised token would grant forever access to the user's data. And AFAICT, the token can't even be invalidated without changing the user name or the server secret (which would in effect invalidate everyone else's auth tokens as well). But maybe I'm missing something here?

OAuth身份验证

这似乎只是在解决问题.现在,我必须存储OAuth机密,而不是在我的服务器应用程序中存储用户的密码.另外,现在我的服务器和客户端代码必须更复杂.

This seems to just move the problem. Now rather than storing users' passwords in my server app, I have to store OAuth secrets. Plus, now my server and client code must be more complicated.

推荐答案

我没有遵循您的确切目标.您似乎暗示用户可能具有密码(应用服务器以编程方式对用户进行身份验证"),但您不希望用户永远不需要知道他们的CouchDB密码".您想要哪种身份验证?

I don't follow your exact goals. You seem to imply users might have passwords ("app server authenticating the users programmatically") but you don't want the users to "ever need to know their CouchDB password". What sort of authentication do you want?

我已经采用两种(半种)常规方法对CouchDB进行身份验证:

There's two (and a half) general approaches I've taken to authentication with CouchDB:

  1. 中间人[ware]"方法,在CouchDB前面有瘦的中间件.该中间件将用户名/密码转发到"/_session",后者基于CouchDB _users数据库产生cookie或错误代码.中间件将此cookie从CouchDB复制到其自己的HTTP响应中,再返回给客户端(或在出现错误的情况下显示一条消息).然后,在需要数据库访问的后续请求中,它将cookie(现在是来自客户端请求)再次转发回数据库.

  1. "Man-in-the-middle[ware]" approach, where I have thin middleware in front of CouchDB. This middleware forwards username/password to the "/_session" which yields a cookie or error codes based on the CouchDB _users database. The middleware copies this cookie from CouchDB onto its own HTTP response back to the client (or displays a message in case of error). Then on subsequent requests, that need database access, it forwards the cookie (now from the client request) back again to the database.

传统方法,您只使用CouchDB作为数据存储并维护自己的用户"条目/索引.确保您使用当前的最佳做法进行密码存储/处理,或使用可为您处理这些详细信息的库.中间件以自身"方式连接到数据库,并基于其自身的会话处理以其自身的逻辑处理读/写权限.

The traditional approach, where you just use CouchDB as a data store and maintain your own "user" entries/indexes. Make sure you use current best practices for password storage/handling or use a library that takes care of those details for you. The middleware connects to the database as "itself" and handles read/write permissions with its own logic based on its own session handling.

或者-一种混合方法-您可以仅使用"/_session" API 来查看CouchDB是否接受有效的用户名和密码.如果是这样,请为该用户创建一个单独的中间件处理的会话. (基本上,您仅将CouchDB的_user数据库用作密码处理库",其余的是传统方法,其中访问控制全部在中间件而不是数据库中实现.)

Or — sort of a hybrid approach — you can use the "/_session" API only to see if CouchDB accepts the username+password as valid. If it does, create a separate middleware-handled session for that user. (Basically you're only using CouchDB's _user database as the "password handling library" and the rest is the traditional approach where the access control is implemented all in the middleware rather than at the database.)

对于现实世界中的生产资料,我倾向于仅使用后两种(或者是先前编号的一半…)—第一种方法很有趣,但是CouchDB缺少文档-级别的读取权限通常意味着在实践中为用户提供对数据库服务器的近乎直接的访问是不可行的.

For real-world production stuff, I've tended to use only the latter two (or one-and-a-half given the earlier numbering…) — the first method is kind of fun, but CouchDB's lack of document-level read permissions usually means that giving users nearly-direct access to the database server is untenable in practice.

更新:您的问题现在很清楚,您希望客户端应用直接与两个服务器对话:该应用(以前称为中间件")服务器 CouchDB(数据库)服务器.我将上面的内容保留在上面,是因为我认为它仍然很有用,并且为此次更新提供了一些背景/背景信息.

UPDATE: your question now makes it clear that you want the client app to talk directly to both servers: the app (formerly "middleware") server and the CouchDB (database) server. I'm leaving the content above because I think it's still somewhat useful and provides a bit of background/context for this update.

您怀疑代理身份验证是错误的解决方案:不是供最终用户使用,但实际上是替换上面#1的cookie转发技巧"部分.也就是说,代理身份验证是指您完全信任一个一方(即您的中间软件)在代表起作用时提供用户信息的情况.用户.但是,您希望用户直接与数据库 对话,而您不能通过X-Auth-CouchDB-Token信任他们.

You are right in your suspicions that Proxy Authentication is the wrong solution: it is not intended for end-user usage, but really to replace the cookie-forwarding "trick" portion of #1 above. That is, proxy authentication is when you fully trust one party (i.e. your middleware) to provide the user information as it works on behalf of a user. But you want the users to talk to the database directly, and you cannot trust them with the X-Auth-CouchDB-Token.

根据您对OAuth选项的判断,我确实认为更接近您想要的东西,但是很明显,您可以通过某种方式针对其他服务对用户进行身份验证,并且不需要存储

I will defer to your judgement on the OAuth option. I do think it is closer to want you want but it is clear that somehow you are authenticating users against a different service and don't need to store per-user keys in CouchDB itself. The request signing required by OAuth 1.0 does mean you'd need support in your client app's HTTP library too.

我看到了一些选项,而无需构建自定义的CouchDB插件,它可以让您的 app 服务器将令牌分发给您的 database 服务器将接受的经过身份验证的用户:

I see a few options, without building a custom CouchDB plugin, that could let your app server hand out a token to authenticated users which your database server will accept:

  1. 毕竟是代理!也就是说,将数据库服务器隐藏在应用程序服务器或其他轻量级自定义反向代理后面.这些中间件所需要做的就是检查您现有的客户端应用程序会话(cookie或其他身份验证标头),如果有效,则设置内部

  1. Proxy after all! That is, hide your database server behind your app server or another lightweight custom reverse-proxy. All this middleware needs to do is check your existing client app session (cookie or other authentication header) and if it's valid, set the internal proxy auth headers that CouchDB will accept — then it forwards the rest of the request/response verbatim.

确定性的密码(每位用户),如果它使您感觉更好.使用仅已知的机密配置您的应用服务器,然后将每个用户密码设置为类似HMAC(username, app_server_secret)的密码.现在,当您要为用户生成令牌时,您的应用服务器可以基于每个用户生成密码.请注意,这确实比仅使用app_server_secret作为每个用户的密码更加安全-CouchDB已经对每个用户密码进行了盐析和哈希处理,因此,如果有人拥有数据库但您的应用程序的配置不重视,攻击者无法将两者区分开.在这两种情况下,防止未经授权使用数据库完全取决于保持app_server_secret机密.

Deterministic password, per-user if it makes you feel better. Configure your app server with a secret known only to it, then set each user password to something like HMAC(username, app_server_secret). Now when you want to generate a token for a user, your app server can generate the password on a per-user basis. Note that this really isn't any more secure than just using the app_server_secret as the password for every user — CouchDB already salts and hashes each user password independently so if someone gets a hold of the database but not your app's configuration values the attacker couldn't tell the two apart. In both cases, preventing unauthorized database usage hinges entirely on keeping app_server_secret secret.

重新实现CouchDB当前的cookie生成算法. CouchDB的cookie算法(查看源文件) data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret)).其中secretcouch_httpd_auth.secret值加上用户的salt值.您可以告诉您的应用服务器 couchdb_httpd_auth/secret 值并且它可以按照相同的步骤生成有效的cookie,您将其提供给客户端应用程序,并且CouchDB会接受它作为其自己的cookie.该cookie将一直有效,直到时间戳记+配置的couch_httpd_auth/timeout.看上去很骇人",尽管您仍然需要以某种方式设置/禁用用户的实际密码,但这可能与您要求的最接近.

Re-implement CouchDB's current cookie generation algorithm. CouchDB's cookie algorithm (view source) is basically data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret)). Where secret is the couch_httpd_auth.secret value plus the user's salt value. You can tell your app server the couchdb_httpd_auth/secret value and it can follow the same steps to generate a valid cookie which you provide to the client app, and CouchDB will accept it as its own. This cookie will be valid until the timestamp + the configured couch_httpd_auth/timeout. As "hacky" as it seems, this is probably the closest to what you are asking for, although you still need to set/disable the users' actual passwords somehow.

这篇关于有什么办法以编程方式生成CouchDB cookie?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆