2010-10-29 33 views
23

Estoy trabajando en una aplicación compatible con CouchDB. Básicamente, quiero crear una base de datos para cada usuario individual de mi aplicación. Para lograr esto, el usuario administrador creará la base de datos, pero en adelante, el usuario tendrá que acceder a su base de datos (usando HTTP Auth sobre SSL). He estado pasando un buen rato descifrando esto.Autorización de CouchDB por base de base de datos

El mejor recurso que he encontrado es en el wiki CouchDB, en este enlace:

http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization

Sugiere que se puede establecer la autorización por base de datos mediante la creación de un documento denominado "_security" a la que se agregue un hash de administradores y lectores. Cuando intento crear ese documento, el mensaje que recibo es "Miembro del documento especial incorrecto: _seguridad".

$ curl -X GET http://localhost:5984 
{"couchdb":"Welcome","version":"1.0.1"} 

¡Cualquier ayuda sería apreciada!

Cheers,

Aaron.

+0

Hola Aaron, ¿cómo lograr la creación de una nueva base de datos cada vez que un usuario se ha registrado? ¿Usaste otro nivel, como php, node, ruby? ¿O descubriste una forma pura de couchapp? – Costa

Respuesta

45

No debería haber ningún problema con ese enfoque.

Digamos que usted tiene una "prueba" de base de datos, y tienen una cuenta de administrador ya:

curl -X PUT http://localhost:5984/test -u "admin:123" 

Ahora puede crear un documento _security para ello:

curl -X PUT http://localhost:5984/test/_security -u "admin:123" -d '{"admins":{"names":[], "roles":[]}, "readers":{"names":["joe"],"roles":[]}}' 

ellos sólo el usuario " joe "podrá leer la base de datos. Para crear el usuario debe tener ya el SHA1 hash de la contraseña:

curl -X POST http://localhost:5984/_users -d '{"_id":"org.couchdb.user:joe","type":"user","name":"joe","roles":[],"password_sha":"c348c1794df04a0473a11234389e74a236833822", "salt":"1"}' -H "Content-Type: application/json" 

Este usuario tiene la contraseña "123" hash utilizando SHA1 con sal "1" (SHA1 ("123" + "1")), por lo él puede leer la base de datos:

curl -X GET http://localhost:5984/test -u "joe:123" 

puede leer cualquier documento ahora en esa base de datos, y ningún otro usuario (pero él y administrador) puede.

ACTUALIZADO: la seguridad escritor

El método anterior emite el problema lector, pero el permiso lector de aquí en realidad significa "leer/escribir documentos comunes", lo que permite escribir documentos, excepto para el diseño de documentos. Los "administradores" en el documento de seguridad pueden escribir do design-docs en esta base de datos.

El otro enfoque, como toma de su propia respuesta, es el "validate_doc_update", que puede tener un validate_doc_update como seguimiento en un archivo:

function(new_doc, old_doc, userCtx) { 
    if(!userCtx || userCtx.name != "joe") { 
     throw({forbidden: "Bad user"}); 
    } 
} 

y empujarlo en un diseño couchdb:

curl -X PUT http://localhost:5984/test/_design/security -d "{ \"validate_doc_update\": \"function(new_doc,doc,userCtx) { if(userCtx || userCtx.name != 'joe') {throw({forbidden: 'Bad user'})}}\"}" --user 'admin:123' 

ellos "Joe" se puede escribir en la base de datos mediante la autenticación básica:

curl -X PUT http://localhost:5984/test/foobar -d '{"foo":"bar"}' -u 'joe:123' 

A medida que también se dirigió puede utilizar la API _SESSION para obtener una cookie de autenticación:

curl http://localhost:5984/_session -v -X POST -d 'name=joe&password=123' -H "Content-Type: application/x-www-form-urlencodeddata" 

Esto devolverá una cabecera como:

Set-Cookie: AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz; Version=1; Path=/; HttpOnly 

Por lo que puede incluir la cookie "AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" en sus próximas solicitudes y serán autenticados.

+0

Debería haber sido más específico. Necesito crear usuarios para * escribir * en la base de datos, no leerlos. Pero he encontrado algunas respuestas a eso, así que estoy actualizando mi respuesta ahora mismo ... –

+0

Aaron, me alegro de ver que progresaste. El lector en el documento de seguridad también tiene permiso para escribir (veo que es un nombre que falla mucho), a excepción de los documentos de diseño. He actualizado mi respuesta para que cubra más sobre permisos de escritura, incluyendo validade_doc_update y session api. – diogok

+0

He configurado algunos usuarios de lectores. Estoy tratando de encontrar la manera de lograr que se autentiquen. la autenticación básica funciona con curl. ¿Configuro otro db para la autenticación (que todos puedan leer)? Entonces redireccionar, la _rewrite de una db apuntando a la _rewrite de la otra? –

5

He estado haciendo más investigación y pruebas, y quiero resumir a dónde he llegado, y qué todavía no funciona para mí.

En primer lugar, me disculpo por quienes leyeron esta pregunta: estaba buscando la manera de establecer permisos para que las personas escriban, no lean, la base de datos. Resulta ser una gran diferencia: las técnicas para crear un "lector" son completamente diferentes de crear un "escritor" (ese término en realidad no existe, aunque me pregunto por qué).

En resumen: tiene que agregar un usuario a la base de datos _users, que es una lista de los usuarios que tienen acceso a cualquier base de datos en su instancia de CouchDB. Yo era capaz de hacer eso mediante la emisión de un comando similar a:

curl -X PUT http://admin:[email protected]:5984/_users/org.couchdb.user:username -d '{"type":"user", "hashed_password":"2bf184a2d152aad139dc4facd7710ee848c2af27", "name":"username", "roles":[]}' 

en cuenta que necesita espacio de nombres al parecer el nombre de usuario con el prefijo "org.couchdb.user". He utilizado un método hash Rubí para obtener el valor hashed_password:

require 'digest/sha1' 
pass_hash = Digest::SHA1.hexdigest(password) 

Esto nos lleva a un usuario aparentemente válida en la base de datos. El siguiente paso es asignar ese usuario como "escritor" (¡ah, ahí está de nuevo!) Para la nueva base de datos que creé. Por lo que podría hacer algo como:

curl -X PUT http://admin:[email protected]:5984/newdatabase 

y luego

curl -X PUT http://admin:[email protected]:5984/newdatabase/_design/security -d @security.json 

Eso .json archivo contiene una función de JavaScript para la tecla "validate_doc_update", y que la función tiene este aspecto:

function(new_doc, old_doc, userCtx) { 
    if(userCtx.name != username) { 
     throw({forbidden: "Please log in first."}); 
    } 
    } 

Es una rotonda, pero tiene sentido. Sin embargo, ahora me encuentro con un problema: al parecer, la variable userCtx no se llena hasta que el usuario se autentica. This article sugiere que todo lo que tiene que hacer es pasar las credenciales a través de una petición HTTP a una base de datos especial _SESSION, así:

curl -X POST http://username:[email protected]:5984/_session 

puedo hacer eso por mi usuario de administración, y la var userCtx se llenará.Pero para mi usuario recién creado, falla:

$ curl http://org.couchdb.user:username:[email protected]:5984/_session 
{"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_db":"_users","authentication_handlers":["cookie","oauth","default"]}} 

Tenga en cuenta que el hash userCtx es nulo. Me pregunto si ese espacio de nombres está causando el problema. Tiene un maldito colon, así que tal vez haya alguna confusión sobre la contraseña. Intenté hacerlo sin el espacio de nombres, y no funciona en absoluto; al menos aquí mi solicitud parece estar llegando a la base de datos y obteniendo una respuesta.

Estoy atascado en este punto. Si alguien puede verificar mis suposiciones y progreso hasta ahora, espero que todos podamos encontrar la manera de hacer que esto funcione.

Gracias!

Aaron.

+0

Si observa lo que está haciendo el control de inicio y fin de sesión de Futon, verá una forma genérica en la que los usuarios pueden iniciar sesión en su aplicación. Si está accediendo mediante curl, puede crear usuarios registrándose como Futon. –

+0

No necesita el prefijo "org.couchdb.user" al autenticar, eso simplemente se ha agregado a _id para el almacenamiento en _users db. Simplemente 'curl http: // username: password @ localhost: 5984/_session' y deberías obtener un objeto userCtx. – natevw

Cuestiones relacionadas