我制作了一个 tornado 应用程序,它应该对在另一台机器上运行的 mongodb 实例运行一些查询。为此,我设置了带有身份验证和用户的 mongodb。我检查了一切正常,并且我可以使用 Robo 3T 应用程序和一个使用 pymongo 的小型同步脚本对 tornado 进行身份验证。
这就是我初始化我的龙卷风应用程序的方式:
class API(tornado.web.Application):
def __init__(self):
settings = dict(
autoreload=True,
compiled_template_cache=False,
static_hash_cache=False,
serve_traceback=True,
cookie_secret="secret",
xsrf_cookies=True,
static_path=os.path.join(os.path.dirname(__file__), "media"),
template_loader=tornado.template.Loader('./templates')
)
mongohost = os.environ.get('MONGOHOST', 'localhost')
mongoport = os.environ.get('MONGOPORT', 27017)
mongouser = os.environ.get('MONGOUSER')
mongopass = os.environ.get('MONGOPASS')
mongodb = os.environ.get('MONGODB')
mongouri = f'mongodb://{mongouser}:{mongopass}@{mongohost}:{mongoport}/{mongodb}'
self.client = motor.motor_tornado.MotorClient(mongouri)
logging.info('connected to mongodb')
self.db = self.client.get_default_database()
logging.info('got mongodb database')
tornado.web.Application.__init__(self, url_patterns, **settings)
def main():
port = 8888
FORMAT = ('%(asctime)s %(levelname) -10s %(name) -30s %(funcName) -35s %(lineno) -5d: %(message)s')
logging.basicConfig(level=logging.DEBUG, format=FORMAT)
tornado.ioloop.IOLoop.configure(TornadoUvloop)
app = API()
app.listen(port)
signal.signal(signal.SIGINT, sig_exit)
logging.info('Tornado server started on port %s' % port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
一切似乎都在运行,直到我的一个实际对数据库执行查询的处理程序被命中。处理程序中的代码如下所示:
cursor = self.application.db['events'].find(
find,
projection
).limit(perpage).skip(page*perpage)
buffsize = 0
try:
while (yield cursor.fetch_next):
message = cursor.next_object()
self.write(json.dumps(message, default=json_util.default))
buffsize += 1
if buffsize >= 10:
buffsize = 0
yield self.flush()
yield self.flush()
except Exception:
logging.error('Could not connect to mongodb', exc_info=True)
此代码在尝试使用身份验证之前运行良好,但现在它引发异常并停止工作:
017-12-12 13:00:20,718 INFO root __init__ 37 : connected to mongodb
2017-12-12 13:00:20,718 INFO root __init__ 39 : got mongodb database
2017-12-12 13:00:20,723 INFO root main 67 : Tornado server started on port 8888
2017-12-12 13:00:25,226 INFO tornado.general _check_file 198 : /Users/liviu/Documents/Work/api_v2/src/api_tmp/handlers/event_list.py modified; restarting server
2017-12-12 13:00:25,469 INFO root __init__ 37 : connected to mongodb
2017-12-12 13:00:25,469 INFO root __init__ 39 : got mongodb database
2017-12-12 13:00:25,472 INFO root main 67 : Tornado server started on port 8888
2017-12-12 13:00:28,152 INFO root get 266 : now querying database
2017-12-12 13:00:28,214 ERROR root get 355 : Could not connect to mongodb
Traceback (most recent call last):
File "/Users/liviu/Documents/Work/api_v2/src/api_tmp/handlers/event_list.py", line 346, in get
while (yield cursor.fetch_next):
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/tornado/gen.py", line 1055, in run
value = future.result()
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/tornado/concurrent.py", line 238, in result
raise_exc_info(self._exc_info)
File "<string>", line 4, in raise_exc_info
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/cursor.py", line 1055, in _refresh
self.__collation))
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/cursor.py", line 892, in __send_message
**kwargs)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/mongo_client.py", line 950, in _send_message_with_response
exhaust)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/mongo_client.py", line 961, in _reset_on_error
return func(*args, **kwargs)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/server.py", line 99, in send_message_with_response
with self.get_socket(all_credentials, exhaust) as sock_info:
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/server.py", line 168, in get_socket
with self.pool.get_socket(all_credentials, checkout) as sock_info:
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/pool.py", line 852, in get_socket
sock_info.check_auth(all_credentials)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/pool.py", line 570, in check_auth
auth.authenticate(credentials, self)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/auth.py", line 486, in authenticate
auth_func(credentials, sock_info)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/auth.py", line 466, in _authenticate_default
return _authenticate_scram_sha1(credentials, sock_info)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/auth.py", line 209, in _authenticate_scram_sha1
res = sock_info.command(source, cmd)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/pool.py", line 477, in command
collation=collation)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/network.py", line 116, in command
parse_write_concern_error=parse_write_concern_error)
File "/Users/liviu/.venv/api/lib/python3.6/site-packages/pymongo/helpers.py", line 210, in _check_command_response
raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: Authentication failed.
2017-12-12 13:00:28,220 INFO tornado.access log_request 2063: 200 GET /event/list/web?starttime=2017-01-01&endtime=2017-02-03T14:00:00&minlatitude=10&maxlatitude=20&minlongitude=10&maxlongitude=20&minmagnitude=2&maxmagnitude=5&mindepth=10&maxdepth=100 (::1) 67.88ms
我能够找到一些关于如何登录和验证 MongoDB 的简单示例,据我所知,这正是我的做法(https://github.com/mongodb/motor/blob/master /doc/examples/authentication.rst)。
任何人都可以了解正在发生的事情以及如何从使用 Motor 的实际工作龙卷风应用程序正确地向 MongoDB 进行身份验证?
PS 我正在使用 Python 3.6、tornado 4.5.2 和电机 1.1。
PPS 与此同时,我发现使用它作为 uri 可以使其正常工作:
mongouri = f'mongodb://{mongouser}:{mongopass}@{mongohost}:{mongoport}/admin'
在上面,我用“admin”数据库替换了 {mongodb}。在客户端连接并在管理数据库上进行身份验证后,我可以继续 get_database(mongodb) 并且它将正常工作。如果有人想更清楚地说明发生了什么,我会接受答案。