2010-10-29 28 views
23

Tôi đang làm việc trên một ứng dụng được CouchDB hỗ trợ. Về cơ bản, tôi muốn tạo một cơ sở dữ liệu cho từng người dùng cá nhân của ứng dụng của tôi. Để thực hiện điều này, người dùng quản trị sẽ tạo ra cơ sở dữ liệu, nhưng trong tương lai, người dùng sẽ cần truy cập cơ sở dữ liệu của họ (sử dụng HTTP Auth qua SSL). Tôi đã có một thời gian để tìm ra điều này.Ủy quyền CouchDB trên Cơ sở Per-Cơ sở dữ liệu

Nguồn tốt nhất mà tôi đã tìm thấy là trong wiki CouchDB, tại liên kết này:

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

Nó gợi ý rằng bạn có thể thiết lập cho phép mỗi cơ sở dữ liệu bằng cách tạo ra một tài liệu gọi là "_security" mà bạn thêm băm của quản trị viên và người đọc. Khi tôi cố gắng tạo tài liệu đó, thư tôi nhận được trở lại là "Thành viên tài liệu đặc biệt xấu: _security".

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

Mọi trợ giúp sẽ được đánh giá cao!

Chúc mừng,

Aaron.

+0

Hey Aaron, làm thế nào bạn thực hiện việc tạo ra một cơ sở dữ liệu mới mỗi khi người dùng đã đăng ký? Bạn có sử dụng một tầng khác, như php, nút, ruby ​​không? Hay bạn đã tìm ra cách đi văng tinh khiết? – Costa

Trả lời

45

Sẽ không có vấn đề gì với sản phẩm đó.

Hãy nói rằng bạn có một cơ sở dữ liệu "thử nghiệm", và có một tài khoản quản trị đã:

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

Bây giờ bạn có thể tạo một tài liệu _security cho nó:

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

Them chỉ có người dùng " joe "sẽ có thể đọc cơ sở dữ liệu. Để tạo người dùng đã bạn phải có sha1 băm mật khẩu:

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" 

Thành viên này có mật khẩu "123" băm sử dụng sha1 với muối "1" (sha1 ("123" + "1")), vì vậy anh ấy có thể đọc cơ sở dữ liệu:

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

Hiện tại, anh ấy có thể đọc bất kỳ tài liệu nào trên cơ sở dữ liệu đó và không có người dùng nào khác (nhưng anh ấy và quản trị viên) có thể.

CẬP NHẬT: Writer an ninh

Các phương pháp trên vấn đề vấn đề người đọc, nhưng cho phép người đọc ở đây thực sự có nghĩa là "đọc/viết tài liệu phổ biến", do đó nó cho phép để viết tài liệu ngoại trừ thiết kế tài liệu. Các "admin" s trong doc _security được phép viết các tài liệu thiết kế trong cơ sở dữ liệu này.

Cách tiếp cận khác, như được lấy từ câu trả lời của riêng bạn, là "validate_doc_update", bạn có thể có một validate_doc_update như sau trong một tập tin:

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

Và đẩy nó vào một thiết kế 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" có thể ghi vào cơ sở dữ liệu sử dụng Basic Authentication:

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

Như bạn cũng giải quyết bạn có thể sử dụng api _SESSION để có được một cookie để xác thực:

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

này sẽ trả về một tiêu đề như:

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

Vì vậy, bạn có thể bao gồm cookie "AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" trong các yêu cầu tiếp theo của bạn và chúng sẽ được xác thực.

+0

Tôi cần phải cụ thể hơn. Tôi cần phải tạo người dùng để * ghi * vào cơ sở dữ liệu, không đọc. Nhưng tôi đã tìm thấy một số câu trả lời cho điều đó, vì vậy tôi đang cập nhật câu trả lời của tôi ngay bây giờ ... –

+0

Aaron, rất vui được thấy bạn đã tiến bộ. Người đọc trong doc _security thực sự cũng được phép viết (tôi thấy đó là một tên rất thiếu), ngoại trừ các tài liệu thiết kế. Tôi đã cập nhật câu trả lời của mình để trang trải nhiều hơn về quyền ghi, bao gồm validade_doc_update và api phiên. – diogok

+0

Tôi đã thiết lập một số người dùng trình đọc. Tôi đang cố gắng tìm ra cách để họ xác thực. xác thực cơ bản hoạt động với curl. Tôi có thiết lập một db khác để xác thực (mà mọi người có thể đọc) không? Sau đó chuyển hướng, các _rewrite của một db trỏ đến _rewrite của người khác? –

5

Tôi đã làm nhiều nghiên cứu và thử nghiệm hơn và tôi muốn tóm tắt nơi tôi đã tiếp cận và những gì vẫn không hiệu quả đối với tôi.

Trước tiên, xin lỗi cho những ai đã đọc câu hỏi này: Tôi đang tìm cách thiết lập quyền cho mọi người viết, không đọc, cơ sở dữ liệu. Hóa ra là một sự khác biệt lớn: các kỹ thuật để tạo ra một "người đọc" hoàn toàn khác với việc tạo ra một "nhà văn" (thuật ngữ đó thực sự không tồn tại, mặc dù tôi tự hỏi tại sao).

Tóm lại: bạn phải thêm người dùng vào cơ sở dữ liệu _users, đây là danh sách người dùng có quyền truy cập vào bất kỳ cơ sở dữ liệu nào trong cá thể CouchDB của bạn. Tôi có thể làm điều đó bằng cách đưa ra một lệnh tương tự như:

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

Lưu ý rằng bạn cần phải đặt tên không gian tên người dùng bằng tiền tố "org.couchdb.user". Tôi đã sử dụng phương pháp băm Ruby để nhận giá trị hashed_password:

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

Điều này là một người dùng có vẻ hợp lệ vào cơ sở dữ liệu. Bước tiếp theo là gán cho người dùng đó là một "người viết" (ha, ở đó nó lại một lần nữa!) Cho cơ sở dữ liệu mới mà tôi đã tạo ra. Vì vậy, tôi có thể làm điều gì đó như:

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

và sau đó

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

Đó .json tập tin chứa một hàm Javascript cho "validate_doc_update" chìa khóa, và chức năng trông như thế này:

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

Đó là vòng xoay, nhưng điều đó có ý nghĩa. Tuy nhiên, hiện tại tôi đang gặp sự cố: dường như biến userCtx không được điền cho đến khi người dùng được xác thực. This article gợi ý rằng tất cả các bạn phải làm là vượt qua các chứng chỉ thông qua một yêu cầu HTTP đến một cơ sở dữ liệu _SESSION đặc biệt, như vậy:

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

tôi có thể làm điều đó cho người dùng admin của tôi, và var userCtx sẽ được áp dụng.Nhưng đối với người dùng mới được tạo của tôi, nó không thành công:

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

Lưu ý rằng băm người dùngCtx là rỗng. Tôi tự hỏi nếu điều đó không gian tên đang gây ra vấn đề? Nó có một dấu hai chấm trong đó, vì vậy có thể có một số nhầm lẫn về mật khẩu? Tôi đã thử làm cho nó mà không có không gian tên, và nó không hoạt động chút nào; ít nhất ở đây yêu cầu của tôi dường như được nhấn cơ sở dữ liệu và nhận được một phản ứng.

Tôi bị kẹt vào thời điểm này. Nếu bất cứ ai có thể kiểm tra các giả định và tiến bộ của tôi cho đến nay, tôi hy vọng tất cả chúng ta có thể tìm ra cách để thực hiện công việc này.

Cảm ơn!

Aaron.

+0

Nếu bạn nhìn vào những gì mà điều khiển đăng nhập và đăng xuất của Futon đang hoạt động, bạn sẽ thấy một cách chung chung mà người dùng của bạn có thể đăng nhập vào ứng dụng của bạn. Nếu bạn đang truy cập thông qua curl, bạn có thể tạo người dùng bằng cách đăng ký như họ trong Futon. –

+0

Bạn không cần tiền tố "org.couchdb.user" khi xác thực, chỉ cần thêm vào _id để lưu trữ trong _users db. Chỉ cần 'curl http: // username: password @ localhost: 5984/_session' và bạn sẽ nhận được một đối tượng userCtx. – natevw

Các vấn đề liên quan