2010-10-29 8 views
23

Je travaille sur une application supportée par CouchDB. Essentiellement, je veux créer une base de données pour chaque utilisateur de mon application. Pour ce faire, l'utilisateur admin créera la base de données, mais à l'avenir, l'utilisateur devra accéder à sa base de données (en utilisant HTTP Auth sur SSL). J'ai passé un moment fou à comprendre cela.Autorisation CouchDB sur une base par base de données

La meilleure ressource que j'ai trouvé est dans le wiki CouchDB, à ce lien:

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

Il suggère que vous pouvez définir l'autorisation par base de données en créant un document intitulé « _security » à laquelle vous ajouter un hachage d'admins et de lecteurs. Lorsque je tente de créer ce document, le message que je reçois est "Membre du document spécial incorrect: _security".

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

Toute aide serait appréciée!

Cheers,

Aaron.

+0

Hey Aaron, comment avez-vous accomplissez la création d'une nouvelle base de données chaque fois qu'un utilisateur inscrit? Avez-vous utilisé un autre niveau, comme php, node, ruby? Ou avez-vous trouvé un moyen de couchage pur? – Costa

Répondre

45

Il ne devrait pas y avoir de problème avec cette approche.

Disons que vous avez une base de données « test », et ont un compte administrateur déjà:

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

Maintenant, vous pouvez créer un document de _security pour elle:

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

Eux seul l'utilisateur " Joe "sera en mesure de lire la base de données. Pour créer l'utilisateur que vous devez avoir le SHA1 mot de passe haché:

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" 

Cet utilisateur le mot de passe « 123 » haché en utilisant SHA1 avec du sel « 1 » (SHA1 (« 123 » + « 1 »)), donc il peut lire la base de données:

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

il peut lire tout document maintenant sur cette base de données, et aucun autre utilisateur (mais lui et admin) peut.

MISE À JOUR: Writer sécurité

La méthode ci-dessus délivre le problème du lecteur, mais l'autorisation de lecteur ici signifie en fait « lecture/écriture docs commun », il permet d'écrire docs sauf pour la conception-docs. Les "admin" dans le document _security sont autorisés à écrire des documents de conception dans cette base de données.

L'autre approche, comme pris de votre propre réponse, est le « validate_doc_update », vous pouvez avoir un validate_doc_update comme suivre dans un fichier:

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

et le pousser dans une conception de 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' 

Them "Joe" peut écrire à la base de données en utilisant l'authentification de base:

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

Comme vous également adressé, vous pouvez utiliser l'api _session pour obtenir un cookie pour l'authentification:

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

Cela renverra un en-tête comme:

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

Vous pouvez inclure le cookie « AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz » dans vos prochaines demandes et ils seront authentifiés.

+0

J'aurais dû être plus précis. J'ai besoin de créer des utilisateurs pour * écrire * dans la base de données, pas lu. Mais j'ai trouvé quelques réponses à cela, donc je suis en train de mettre à jour ma réponse maintenant ... –

+0

Aaron, ravi de vous voir progresser. Le lecteur dans le document _security est en fait autorisé à écrire aussi (je vois que c'est un nom très manquant), sauf pour les documents de conception. J'ai mis à jour ma réponse pour en savoir plus sur les autorisations d'écriture, y compris validade_doc_update et api de session. – diogok

+0

J'ai mis en place des utilisateurs de lecteurs. J'essaie de trouver comment les authentifier. l'authentification de base fonctionne avec curl. Dois-je configurer un autre db à l'authentification (que tout le monde peut lire)? Puis rediriger, le _rewrite d'un db pointant vers le _rewrite de l'autre? –

5

J'ai fait plus de recherches et de tests, et je veux résumer où je suis arrivé, et ce qui ne fonctionne toujours pas pour moi. Tout d'abord, excuses pour ceux qui ont lu cette question: Je cherchais des moyens de définir des autorisations pour les gens à écrire, pas à lire, la base de données. Il s'avère être une grande différence: les techniques pour créer un «lecteur» sont entièrement différentes de la création d'un «écrivain» (ce terme n'existe pas réellement, bien que je me demande pourquoi).

En bref: vous devez ajouter un utilisateur à la base de données _users, qui est une liste des utilisateurs ayant accès à n'importe quelle base de données dans votre instance CouchDB. J'ai pu le faire en émettant une commande similaire à:

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

Notez que vous devez namespace apparemment le nom d'utilisateur avec le préfixe « org.couchdb.user ». J'ai utilisé une méthode de hachage Ruby pour obtenir la valeur de hashed_password:

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

Cela devient un utilisateur apparemment valide dans la base de données. L'étape suivante consiste à assigner cet utilisateur en tant que "écrivain" (ha, il est là encore!) Pour la nouvelle base de données que j'ai créée. Donc, je pourrais faire quelque chose comme:

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

puis

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

Ce .json fichier contient une fonction Javascript pour la touche "validate_doc_update", et cette fonction ressemble à ceci:

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

C'est un rond-point, mais c'est logique. Cependant, je rencontre maintenant un problème: apparemment, la variable userCtx n'est pas remplie tant que l'utilisateur n'est pas authentifié. This article suggère que tout ce que vous avez à faire est de passer les informations d'identification via une requête HTTP à une base de données spéciale _session, comme ceci:

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

Je peux le faire pour mon utilisateur admin et le var userCtx sera peuplée.Mais pour mon utilisateur nouvellement créé, il échoue:

$ 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"]}} 

Notez que le hachage userCtx est null. Je me demande si cette chose namespace provoque le problème? Il y a un deux-points bizarre dedans, alors peut-être qu'il y a une certaine confusion au sujet du mot de passe? J'ai essayé de le faire sans l'espace de nom, et ça ne marche pas du tout; au moins ici, ma demande semble frapper la base de données et obtenir une réponse.

Je suis bloqué à ce stade. Si quelqu'un peut vérifier mes hypothèses et mes progrès jusqu'à maintenant, j'espère que nous pourrons tous comprendre comment faire pour que cela fonctionne.

Merci!

Aaron.

+0

Si vous regardez ce que fait le contrôle de connexion et de déconnexion de Futon, vous verrez un moyen générique pour vos utilisateurs de se connecter à votre application. Si vous accédez via curl, vous pouvez créer des utilisateurs en vous inscrivant comme eux dans Futon. –

+0

Vous n'avez pas besoin du préfixe "org.couchdb.user" lors de l'authentification, c'est juste ajouté au _id pour le stockage dans la base de données _users. Simplement 'curl http: // nom d'utilisateur: mot de passe @ localhost: 5984/_session' et vous devriez obtenir un objet userCtx. – natevw