我已经从 fons 分叉了 cl-mongo(通用 lisp MongoDB 库)存储库,因为它已经停止维护并且不支持 SCRAM-SHA-1 登录过程。这是我的分叉:https ://github.com/mprelude/cl-mongo——主要的变化是添加了对cl-scram(我的 SCRAM 实现)的依赖,并添加了一个 bson 二进制通用容器。
我仍在尝试发送初始消息,所以问题不在于密码错误,因为尚未使用。
为什么这部分身份验证失败?如果我想将 MESSAGE 中的内容传输到 mongo,任何人都可以确认 BINARY-MESSAGE 是否是我应该发送的内容?
这是我的电话,添加了一些调试输出:
* (asdf:load-system :cl-mongo)
T
* (cl-mongo:db.use "test")
"test"
* (cl-mongo:db.auth "aurumrw" "pencil" :mechanism :SCRAM-SHA-1)
(kv-container : #(#S(CL-MONGO::PAIR :KEY saslStart :VALUE 1)
#S(CL-MONGO::PAIR :KEY mechanism :VALUE SCRAM-SHA-1)
#S(CL-MONGO::PAIR
:KEY payload
:VALUE [CL-MONGO::BSON-BINARY-GENERIC] [binary data of type 0] ))
((CL-MONGO::BINARY-MESSAGE
. #(98 105 119 115 98 106 49 104 100 88 74 49 98 88 74 51 76 72 73 57 83 87
116 122 101 84 100 78 101 71 100 97 90 71 52 53 85 69 86 113 87 108 104
85 89 108 78 75 89 106 74 80 79 87 78 84 99 49 108 84 82 68 99 61))
(CL-MONGO::MESSAGE . "n,,n=aurumrw,r=Iksy7MxgZdn9PEjZXTbSJb2O9cSsYSD7")
(CL-MONGO::CODE . 18) (CL-MONGO::OK . 0.0d0)
(CL-MONGO::ERRMSG . "Authentication failed.")))
值得注意的是,我认为 Mongo 必须正确读取我的请求,因为消息是“身份验证失败”(错误代码 18),这表明它理解我已请求 SASL 对话。
我相信我遇到的问题是基于有效负载,无论是内容(base64 的初始消息,作为八位字节)或格式。
借鉴MongoDB 文档以及原始讨论的工作方式,这是我重写的 db.auth 函数:
(defmethod db.auth ((username string) (password string) &key (mongo (mongo)) (mechanism :SCRAM-SHA-1))
(cond ((equal mechanism :SCRAM-SHA-1)
;; SCRAM-SHA-1 Login
(let* ((nonce (cl-scram:gen-client-nonce))
(pwd (concatenate 'string username ":mongo:" password))
(md5-pwd (hex-md5 pwd))
(md5-pwd-str (ironclad:byte-array-to-hex-string md5-pwd))
(initial-message (cl-scram:gen-client-initial-message :username username
:nonce nonce))
(request (kv (kv "saslStart" 1)
(kv "mechanism" "SCRAM-SHA-1")
(kv "payload"
(bson-binary :generic (ironclad:ascii-string-to-byte-array
(cl-scram:base64-encode initial-message))))))
(response (car (docs (db.find "$cmd" request :limit 1 :mongo mongo))))
(retval (pairlis '(errmsg ok code message binary-message)
(list (get-element "errmsg" response)
(get-element "ok" response)
(get-element "code" response)
initial-message
(ironclad:ascii-string-to-byte-array (cl-scram:base64-encode initial-message))))))
(list request retval)))
((equal mechanism :MONGODB-CR)
;; MONGODB-CR Login.
(let* ((nonce (get-element "nonce" (car (docs (db.run-command 'getnonce :mongo mongo)))))
(pwd (concatenate 'string username ":mongo:" password))
(md5-pwd (hex-md5 pwd))
(md5-pwd-str (ironclad:byte-array-to-hex-string md5-pwd))
(md5-key (hex-md5 (concatenate 'string nonce username md5-pwd-str)))
(md5-key-str (ironclad:byte-array-to-hex-string md5-key))
(request (kv (kv "authenticate" 1)
(kv "user" username)
(kv "nonce" nonce)
(kv "key" md5-key-str)))
(retval (get-element "ok" (car (docs (db.find "$cmd" request :limit 1 :mongo mongo))))))
(if retval t nil)))
(t nil)))