简体   繁体   English

Tornado使用Motor向MongoDB进行身份验证

[英]Tornado authenticating to MongoDB using Motor

I made a tornado app that is supposed to run some queries against a mongodb instance running on another machine. 我制作了一个龙卷风应用程序,该应用程序应该针对在另一台计算机上运行的mongodb实例运行一些查询。 To this purpose I have set up mongodb with authentication and users. 为此,我使用身份验证和用户设置了mongodb。 I have checked that everything works and that I can authenticate to tornado using the Robo 3T app and a small synchronous script that uses pymongo. 我检查了一切是否正常,并且可以使用Robo 3T应用程序和使用pymongo的小型同步脚本对龙卷风进行身份验证。

This is how I initialize my tornado application: 这是我初始化龙卷风应用程序的方式:

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()

Everything appears to run until one of my handlers that actually performs queries against the database is hit. 一切似乎都在运行,直到击中实际对数据库执行查询的处理程序之一为止。 Code from the handler looks like this: 处理程序中的代码如下所示:

      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)

This code worked just fine before trying to use authentication but now it raises exceptions and stoped working: 这段代码在尝试使用身份验证之前工作得很好,但是现在它引发了异常并停止了工作:

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

I was able to find some simple examples on how to log in and authenticate to MongoDB and as far as I can figure, that is exactly how I am also doing it ( https://github.com/mongodb/motor/blob/master/doc/examples/authentication.rst ). 我能够找到一些有关如何登录和验证MongoDB的简单示例,据我所知,这正是我也正在这样做的方式( https://github.com/mongodb/motor/blob/master /doc/examples/authentication.rst )。

Can anybody shed some light on what is going on and how to properly authenticate to MongoDB from an actual working tornado application using Motor? 任何人都可以对发生的事情以及如何使用Motor进行实际的工作龙卷风应用程序向MongoDB进行正确身份验证有所了解吗?

PS I am using Python 3.6, tornado 4.5.2 and motor 1.1. PS我正在使用Python 3.6,龙卷风4.5.2和马达1.1。

PPS In the meantime I have discovered that using this as the uri makes it work properly: PPS同时,我发现将它用作uri使其可以正常工作:

mongouri = f'mongodb://{mongouser}:{mongopass}@{mongohost}:{mongoport}/admin'

In the above, I replaced {mongodb} with the "admin" db. 在上面,我用“ admin”数据库替换了{mongodb}。 After the client gets connected and authenticated on the admin database, I can proceed to get_database(mongodb) and it will work properly. 客户端连接到管理数据库并通过身份验证后,我可以继续进行get_database(mongodb),它将正常运行。 If anyone cares to more clearly articulate what is going on I will accept the answer. 如果有人想更清楚地阐明正在发生的事情,我会接受答案。

From the mongodb docs : 来自mongodb docs

authSource authSource

Specify the database name associated with the user's credentials. 指定与用户凭据关联的数据库名称。 authSource defaults to the database specified in the connection string. authSource默认为连接字符串中指定的数据库。

That explains why it works if you specify "admin" as target database. 这说明了如果您将“ admin”指定为目标数据库,为什么它可以工作。 So in your case you should use: 因此,在您的情况下,您应该使用:

mongouri = f'mongodb://{mongouser}:{mongopass}@{mongohost}:{mongoport}/{mongodb}?authSource=admin'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM