2010-10-29 14 views
23

Sto lavorando su un'applicazione supportata da CouchDB. In sostanza, voglio creare un database per ogni singolo utente della mia app. Per fare ciò, l'utente admin creerà il database, ma andando avanti, l'utente dovrà accedere al proprio database (usando HTTP Auth su SSL). Ho avuto un sacco di tempo per capirlo.Autorizzazione CouchDB su base Per-database

La migliore risorsa che ho trovato è nel wiki CouchDB, a questo link:

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

Essa suggerisce che è possibile impostare l'autorizzazione per-database creando un documento denominato "_Sicurezza" a cui si aggiungi un hash di amministratori e lettori. Quando tento di creare quel documento, il messaggio che ottengo è "Membro del documento speciale non valido: _security".

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

Qualsiasi aiuto sarebbe apprezzato!

Cheers,

Aaron.

+0

Hey Aaron, come hai fatto a realizzare la creazione di un nuovo database ogni volta che un utente registrato? Hai usato un altro livello, come php, node, ruby? O hai scoperto un modo di couchapp puro? – Costa

risposta

45

Non ci dovrebbero essere problemi con quell'abuso.

Diciamo che si dispone di un "test" del database, e hanno un account amministratore già:

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

Ora è possibile creare un documento _Sicurezza per esso:

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

loro solo l'utente " joe "sarà in grado di leggere il database. Per creare l'utente è necessario avere già la sha1 password con hash:

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" 

Questo utente ha la password "123" hash usando SHA1 con il sale "1" (sha1 ("123" + "1")), in modo da può leggere il database:

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

Sa leggere qualsiasi documento ora in quel database, e nessun altro utente (ma lui e admin) può.

AGGIORNAMENTO: la sicurezza Writer

Il metodo di cui sopra emette il problema lettore, ma il permesso lettore di qui in realtà significa "leggere/scrivere documenti comuni", in modo da permette di scrivere documenti, tranne per il design-docs. Gli "admin" nel documento _security sono autorizzati a scrivere do design-docs in questo database.

L'altro approccio, come preso dalla propria risposta, è il "validate_doc_update", si può avere una validate_doc_update come seguire in un file:

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

e spingerlo in un disegno 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' 

Loro "Joe" può scrivere al database utilizzando l'autenticazione di base:

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

Come anche lei si è rivolto è possibile utilizzare l'API _SESSION per ottenere un cookie per l'autenticazione:

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

Ciò restituirà un colpo di testa come:

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

Quindi è possibile includere il cookie "AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" nelle tue prossime richieste e saranno autenticati.

+0

Avrei dovuto essere più specifico. Devo creare utenti per * scrivere * nel database, non leggere. Ma ho trovato delle risposte, quindi sto aggiornando la mia risposta in questo momento ... –

+0

Aaron, piacere di vederti progredire. Il lettore del documento _security è in realtà autorizzato a scrivere anche (vedo che manca molto il nome principale), ad eccezione dei documenti di progettazione. Ho aggiornato la mia risposta per includere ulteriori informazioni sulle autorizzazioni di scrittura, tra cui validade_doc_update e session api. – diogok

+0

Ho impostato alcuni utenti di lettori. Sto cercando di capire come farli autenticare. l'autenticazione di base funziona con arricciatura. Configuro un altro db per l'autenticazione (che tutti possono leggere)? Quindi reindirizzare, il _rewrite di un db che punta al _rewrite dell'altro? –

5

Ho fatto più ricerca e sperimentazione, e voglio riassumere in cui ho avuto modo, e ciò che ancora non funziona per me.

Prima di tutto, le scuse per coloro che leggono questa domanda: ero alla ricerca di modi per impostare i permessi per le persone a scrivere, non legge, il database. Risulta essere una grande differenza: le tecniche per creare un "lettore" sono completamente diverse dalla creazione di uno "scrittore" (il termine in realtà non esiste, anche se mi chiedo perché).

In breve: si deve aggiungere un utente al database _users, che è una lista degli utenti che hanno accesso a qualsiasi database nell'istanza CouchDB. Sono stato in grado di farlo con un comando simile a:

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

Nota è necessario namespace a quanto pare il nome utente con il prefisso "org.couchdb.user". Ho usato un metodo di hashing Ruby per ottenere il valore hashed_password:

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

Questo diventa un utente apparentemente valida nel database. Il prossimo passo è assegnare quell'utente come "scrittore" (ha, eccolo di nuovo!) Per il nuovo database che ho creato. Quindi potrei fare qualcosa di simile:

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

e poi

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

Che .json file contiene una funzione JavaScript per la chiave "validate_doc_update", e che la funzione assomiglia a questo:

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

È rotonda, ma ha senso. Tuttavia, ora sto incontrando un problema: a quanto pare la variabile userCtx non viene popolata finché l'utente non viene autenticato. This article suggerisce che tutto ciò che dovete fare è passare le credenziali attraverso una richiesta HTTP a un database speciale _SESSION, in questo modo:

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

posso farlo per il mio utente admin e la var userCtx verranno popolati.Ma per il mio utente appena creato, non riesce:

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

Nota l'hash userCtx è nullo. Mi chiedo se quella cosa dello spazio dei nomi sta causando il problema? Ha un punto debole, quindi forse c'è qualche confusione sulla password? Ho provato a farlo senza lo spazio dei nomi, e non funziona affatto; almeno qui la mia richiesta sembra colpire il database e ottenere una risposta.

Sono bloccato a questo punto. Se qualcuno può verificare le mie supposizioni e progredire finora, spero che tutti noi possiamo capire come farlo funzionare.

Grazie!

Aaron.

+0

Se guardi cosa sta facendo il controllo di accesso e disconnessione di Futon, vedrai un modo generico con cui gli utenti possono accedere alla tua app. Se si accede tramite arricciatura, è possibile creare utenti registrandoli come in Futon. –

+0

Non è necessario il prefisso "org.couchdb.user" quando si effettua l'autenticazione, che è stato appena aggiunto a _id per l'archiviazione nel db _users. Semplicemente 'curl http: // username: password @ localhost: 5984/_session' e dovresti ottenere un oggetto userCtx. – natevw