我将有一个应用客户端(移动/网络),一个应用服务器和CouchDB服务器.客户端应用程序将对应用程序服务器进行身份验证,然后我的理想情况是我的应用程序服务器以编程方式对用户进行身份验证,然后将10分钟的cookie发送到客户端应用程序.
也就是说,我希望应用服务器代表应用客户端的用户从CouchDB服务器请求Cookie,然后仅将cookie发送到应用客户端.
应用服务器可以代表经过身份验证的用户POST到_session,但这需要:
>在应用服务器中维护用户密码列表
>为所有用户使用单个已知密码
>为每个身份验证请求随机重置密码
出于安全考虑,#3似乎是最好的,但这似乎是额外的工作,并且是DB的额外往返(尽管不是昂贵的).所以我的问题是:作为管理员,是否有代表用户生成cookie的方式,而根本不使用用户的密码?
这也可能允许我完全拒绝来自我的app服务器的_session请求,作为一项额外的安全措施.
为了完整起见,我还要提到我已经看过这些其他选项,并发现他们想要:
x_auth_token永不过期的事实对我来说是令人担忧的.这意味着受损的令牌将永久授予用户数据的访问权限.而且,如果不更改用户名或服务器密钥(这实际上会使其他人的auth令牌无效),令牌甚至无法失效.但也许我在这里错过了一些东西?
> OAuth auth
这似乎只是解决了这个问题.现在,我不是将用户的密码存储在我的服务器应用程序中,而是存储OAuth的秘密.另外,现在我的服务器和客户端代码必须更复杂.
解决方法
我用CouchDB进行身份验证的方法有两种(一半):
>“Man-in-the-middle [ware]”方法,我在CouchDB前面有瘦的中间件.此中间件将用户名/密码转发到“/ _session”,根据CouchDB _users数据库生成cookie或错误代码.中间件将此cookie从CouchDB复制到自己的HTTP响应中,然后返回给客户端(或者在出现错误时显示消息).然后,在需要数据库访问的后续请求中,它将cookie(现在从客户端请求)转发回数据库.
>传统方法,您只需将CouchDB用作数据存储并维护自己的“用户”条目/索引.确保使用当前的密码存储/处理最佳实践,或使用可以为您处理这些详细信息的库.中间件以“自身”的形式连接到数据库,并根据自己的会话处理使用自己的逻辑处理读/写权限.
>或者 – 一种混合方法 – 您只能使用“/ _session”API来查看CouchDB是否接受用户名密码为有效.如果是,请为该用户创建单独的中间件处理会话. (基本上你只使用CouchDB的_user数据库作为“密码处理库”,其余的是传统的方法,在中间件而不是数据库中实现访问控制.)
对于现实生产的东西,我倾向于只使用后两个(或者给出早期编号的一半……) – 第一种方法很有趣,但CouchDB缺乏文档级读取权限通常意味着在实践中让用户几乎直接访问数据库服务器是站不住脚的.
更新:您的问题现在清楚地表明您希望客户端应用程序直接与两个服务器通信:应用程序(以前称为“中间件”)服务器和CouchDB(数据库)服务器.我将离开上面的内容,因为我认为它仍然有用,并为此更新提供了一些背景/上下文.
您怀疑Proxy Authentication是错误的解决方案是正确的:它不是为了最终用户使用,而是真正取代上面#1的cookie转发“技巧”部分.也就是说,代理身份验证是指您完全信任一方(即您的中间件)以提供用户信息,因为它代表用户工作.但是您希望用户直接与数据库通信,并且您不能使用X-Auth-CouchDB-Token信任它们.
我将推迟您对OAuth选项的判断.我确实认为它更接近你想要的但是很明显,你不知道如何根据不同的服务对用户进行身份验证,而不需要存储per-user keys in CouchDB本身. OAuth 1.0要求的请求签名确实意味着您还需要在客户端应用程序的HTTP库中提供支持.
我看到一些选项,没有构建自定义CouchDB插件,可以让您的应用服务器将令牌分发给数据库服务器将接受的经过身份验证的用户:
>代理毕竟!也就是说,将数据库服务器隐藏在应用服务器或其他轻量级自定义反向代理之后.所有这些中间件需要做的是检查您现有的客户端应用程序会话(cookie或其他身份验证标头),如果它有效,设置CouchDB将接受的内部proxy auth headers – 然后它逐字转发其余的请求/响应.
>确定性密码,每个用户,如果它让你感觉更好.使用仅为其知道的秘密配置您的应用服务器,然后将每个用户密码设置为HMAC(用户名,app_server_secret).现在,当您想为用户生成令牌时,您的应用服务器可以基于每个用户生成密码.请注意,这实际上并不比使用app_server_secret作为每个用户的密码更安全 – CouchDB已经独立地对每个用户密码进行盐分和哈希处理,因此如果有人获取数据库而不是应用程序的配置值,则攻击者无法告诉两者分开.在这两种情况下,防止未经授权的数据库使用完全取决于保持app_server_secret的秘密.
>重新实现CouchDB当前的cookie生成算法. CouchDB的cookie算法(view source)基本上是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 / timeout的时间戳之前有效.尽管看起来像“hacky”,但这可能是你所要求的最接近的,尽管你仍然需要以某种方式设置/禁用用户的实际密码.