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

时间:2017-12-12 10:58:51

标签: python mongodb authentication tornado tornado-motor

我创建了一个龙卷风应用程序,它应该针对在另一台机器上运行的mongodb实例运行一些查询。为此我设置了具有身份验证和用户的mongodb。我已经检查过一切正常,我可以使用Robo 3T应用程序和使用pymongo的小型同步脚本对龙卷风进行身份验证。

这是我初始化龙卷风应用程序的方式:

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进行适当的身份验证吗?

P.S。我使用的是Python 3.6,龙卷风4.5.2和电机1.1。

P.P.S。与此同时,我发现使用它作为uri使其正常工作:

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

在上面,我用&#34; admin&#34;替换了{mongodb}。 D b。客户端在管理数据库上连接并进行身份验证后,我可以继续使用get_database(mongodb),它将正常工作。如果有人愿意更清楚地表达正在发生的事情,我会接受答案。

1 个答案:

答案 0 :(得分:0)

来自the mongodb docs

  

authSource

     

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

这说明了如果您将“ admin”指定为目标数据库,为什么它可以工作。 因此,在您的情况下,您应该使用:

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