Авторизация CouchDB на основе базы данных
Я работаю над приложением, поддерживаемым CouchDB. По сути, я хочу создать базу данных для каждого отдельного пользователя моего приложения. Для этого пользователь-администратор создаст базу данных, но в дальнейшем пользователь должен будет получить доступ к своей базе данных (используя HTTP Auth через SSL). У меня было время понять это.
Лучший ресурс, который я нашел, находится в вики CouchDB по этой ссылке:
http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization
Это говорит о том, что вы можете настроить авторизацию для каждой базы данных, создав документ под названием "_security", к которому вы добавляете хэш админов и читателей. Когда я пытаюсь создать этот документ, сообщение, которое я получаю, это "Плохой специальный элемент документа: _security".
$ curl -X GET http://localhost:5984
{"couchdb":"Welcome","version":"1.0.1"}
Любая помощь будет оценена!
Приветствия,
Аарон.
Ответы
Ответ 1
Не должно быть проблем с этим aproach.
Скажем, у вас есть "тест" базы данных и уже есть учетная запись администратора:
curl -X PUT http://localhost:5984/test -u "admin:123"
Теперь вы можете создать для него документ _security:
curl -X PUT http://localhost:5984/test/_security -u "admin:123" -d '{"admins":{"names":[], "roles":[]}, "readers":{"names":["joe"],"roles":[]}}'
Только пользователь "joe" сможет прочитать базу данных. Чтобы создать пользователя, у вас должен быть уже сохраненный пароль sha1:
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"
У этого пользователя есть пароль "123" с использованием sha1 с солью "1" (sha1 ( "123" + "1" )), поэтому он может читать базу данных:
curl -X GET http://localhost:5984/test -u "joe:123"
Он может читать любой документ в этой базе данных, и ни один другой пользователь (но он и администратор) не может.
ОБНОВЛЕНО: Безопасность Writer
Вышеупомянутый метод выдает проблему с читателем, но здесь разрешение читателя на самом деле означает "чтение/запись общих документов", поэтому он позволяет писать документы, за исключением проектных документов. "Администраторам" в документе _security разрешено писать do design-docs в этой базе данных.
Другой подход, взятый из вашего собственного ответа, - "validate_doc_update", вы можете иметь validate_doc_update, как указано в файле:
function(new_doc, old_doc, userCtx) {
if(!userCtx || userCtx.name != "joe") {
throw({forbidden: "Bad user"});
}
}
И вставьте его в конструкцию 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" может записывать в базу данных с помощью Basic Authentication:
curl -X PUT http://localhost:5984/test/foobar -d '{"foo":"bar"}' -u 'joe:123'
Как вы также обратились, вы можете использовать _session api для получения файла cookie для аутентификации:
curl http://localhost:5984/_session -v -X POST -d 'name=joe&password=123' -H "Content-Type: application/x-www-form-urlencodeddata"
Это вернет заголовок, например:
Set-Cookie: AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz; Version=1; Path=/; HttpOnly
Таким образом, вы можете включить cookie файл "AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" в свои следующие запросы, и они будут аутентифицированы.
Ответ 2
Я проводил больше исследований и тестирования, и я хочу обобщить, к чему я пришел, и что еще не работает для меня.
Во-первых, извиняюсь за тех, кто читает этот вопрос: я искал способы установить разрешения для людей, чтобы писать, а не читать, базу данных. Оказывается, будет большая разница: методы создания "читателя" полностью отличаются от создания "писателя" (этот термин на самом деле не существует, хотя мне интересно, почему).
Вкратце: вы должны добавить пользователя в базу данных _users, которая представляет собой список пользователей, которые имеют доступ к любой базе данных в вашем экземпляре CouchDB. Я смог сделать это, выпустив команду, похожую на:
curl -X PUT http://admin:[email protected]:5984/_users/org.couchdb.user:username -d '{"type":"user", "hashed_password":"2bf184a2d152aad139dc4facd7710ee848c2af27", "name":"username", "roles":[]}'
Обратите внимание, что вам нужно, по-видимому, указать имя пользователя с префиксом "org.couchdb.user". Я использовал метод хеширования Ruby для получения значения hashed_password:
require 'digest/sha1'
pass_hash = Digest::SHA1.hexdigest(password)
Это приводит к действительным действительным пользователям в базе данных. Следующий шаг - назначить этого пользователя как "писателя" (ха, там он снова!) Для новой базы данных, которую я создал. Поэтому я могу сделать что-то вроде:
curl -X PUT http://admin:[email protected]:5984/newdatabase
а затем
curl -X PUT http://admin:[email protected]:5984/newdatabase/_design/security -d @security.json
Этот .json файл содержит функцию Javascript для ключа validate_doc_update, и эта функция выглядит так:
function(new_doc, old_doc, userCtx) {
if(userCtx.name != username) {
throw({forbidden: "Please log in first."});
}
}
Это круговое движение, но это имеет смысл. Однако теперь я сталкиваюсь с проблемой: видимо, переменная userCtx не заполняется до тех пор, пока пользователь не будет аутентифицирован. В этой статье говорится, что все, что вам нужно сделать, это передать учетные данные через HTTP-запрос в специальную базу данных _session, например:
curl -X POST http://username:[email protected]:5984/_session
Я могу сделать это для моего администратора, а userCtx var будет заполнен. Но для моего вновь созданного пользователя это терпит неудачу:
$ 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"]}}
Обратите внимание, что hash hasCTX имеет значение null. Интересно, вызывает ли это пространство имен проблему? У меня получилось толчок дурмана, так что, может быть, есть какая-то путаница в пароле? Я пробовал сделать это без пространства имен, и он вообще не работает; по крайней мере, здесь мой запрос попадает в базу данных и получает ответ.
Я застрял на этом. Если кто-то может проверить мои предположения и прогресс до сих пор, я надеюсь, что мы все можем понять, как это сделать.
Спасибо!
Аарон.
Ответ 3
Вы можете проверить Мэтт Вудворд - окончательное руководство по аутентификации и безопасности CouchDB http://blog.mattwoodward.com/2012/03/definitive-guide-to-couchdb.html