0

我制作了一个 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) 并且它将正常工作。如果有人想更清楚地说明发生了什么,我会接受答案。

4

1 回答 1

0

mongodb 文档

授权来源

指定与用户凭据关联的数据库名称。authSource 默认为连接字符串中指定的数据库。

这就解释了为什么如果您将“admin”指定为目标数据库它会起作用。因此,在您的情况下,您应该使用:

mongouri = f'mongodb://{mongouser}:{mongopass}@{mongohost}:{mongoport}/{mongodb}?authSource=admin'
于 2018-10-29T09:12:34.870 回答