Tornado用户身份验证

时间:2016-02-05 11:51:56

标签: authentication tornado credentials

我有一组 API ,每个都是 BaseRequestHandler 的子类。在 BaseRequestHandler 中,我将设置一个 self.user 变量,其中包含一个包含所有用户凭据作为值的字典。

例如:

self.user = {
    "id": 0,
    "ip": "user ip",
    "country_name": "user country name",
    ...
}

我的问题是,如果对我的一组API的第一个传入请求未完成,则对另一个API的第二个传入请求将覆盖用户凭据,因此我不匹配当我需要使用这些凭据时,用户在第一个传入请求中的凭据。

换句话说,在第一个请求中,我拥有第二个传入请求的用户凭据。

如何跟踪每个传入的请求以避免用户的凭据不匹配?

你有什么建议吗?

提前致谢!

修改

在我们的项目中,我们有多个子类,我们已经实现了异步多处理Web服务器。

Application实例中,我们有一个这样的API列表:

application = tornado.web.Application([
    (r"/api1/info1", api1.InfoOneRequestHandler),
    (r"/api1/info2", api1.InfoTwoRequestHandler),
    (r"/api2/info1", api2.InfoOneRequestHandler),
    (r"/api3/info1", api3.InfoOneRequestHandler)
])

这些公开的API中的每一个都是子类,对于每一个API,我们都有一个名为BaseAPIOneRequestHandlerBaseAPITwoRequestHandlerBaseAPIThreeRequestHandler的特定超类。

这些超类(BaseAPIOneRequestHandlerAPITwoBaseRequestHandlerBaseAPIThreeRequestHandler)也是子类,它们都继承了名为BaseAPIRequestHandler的主(共享)超类。

BaseAPIRequestHandler包含一种方法,用于检索调用该特定API的特定User Id的权限和权限。

@tornado.gen.coroutine
def _retrieve_user_info(self, user_id):
    self.user["id"] = ...
    self.user["country_name"] = ...
    self.user["country_code"] = ...
    ... POPULATE DATA ...

在每个子类(BaseAPIOneRequestHandlerBaseAPITwoRequestHandlerBaseAPIThreeRequestHandler)中,我们称之为方法:

_request = tornado.escape.json_decode(self.request.body)
yield self._retrieve_user_info(_request["user_id"])

逻辑或多或少如下:

application = tornado.web.Application([
    (r"/api1/info1", api1.InfoOneRequestHandler),
    (r"/api1/info2", api1.InfoTwoRequestHandler),
    (r"/api2/info1", api2.InfoOneRequestHandler),
    (r"/api3/info1", api3.InfoOneRequestHandler)
])

class InfoOneRequestHandler(BaseAPIOneRequestHandler):
    @tornado.gen.coroutine
    def post(self, *args, **kwargs):
        """
        The problem occurs within this method when we're going to 
        retrieve information about the user.
        """
        ... PERFORM OTHER INSTRUCTIONS ...

        # _id variable will contain the ID of the user who's calling
        # another API (it override the key "id" of the user
        # who's calling the first API).
        # When two users are calling two different APIs, both "id"
        # keys will contain the ID of second user
        _id = self.user["id"]

        ... REMAINING OPERATIONS ...

class BaseAPIOneRequestHandler(BaseAPIRequestHandler):
    @tornado.gen.coroutine
    def prepare(self):
        """
        Here we're going to call the method to update the user's
        credentials.
        """
        super(BaseAPIOneRequestHandler, self).prepare()

        ... OTHER LOCAL THINGS ...

        _request = tornado.escape.json_decode(self.request.body)
        yield self._retrieve_user_info(_request["user_id"])

    @tornado.gen.coroutine
    def on_finish(self):
        ... API ONE LOCAL THINGS ...

        super(BaseAPIOneRequestHandler, self).on_finish()

class BaseAPIRequestHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def prepare(self):
        ... POPULATE GLOBAL DATA ...

    @tornado.gen.coroutine
    def get(self, *args, **kwargs):
        self.write("Method not allowed")

    @tornado.gen.coroutine
    def _retrieve_user_info(self, user_id):
        """
        Here we're going to update the user's information base on the 
        user's identifier (user_id).
        """
        self.user["id"] = ...
        self.user["country_name"] = ...
        self.user["country_code"] = ...

        ... POPULATE USER DATA ...

    @tornado.gen.coroutine
    def options(self, *args, **kwargs):
        self.set_header("Access-Control-Allow-Headers", self.request.headers["Access-Control-Request-Headers"])
        self.set_header("Access-Control-Allow-Methods", self.request.headers["Access-Control-Request-Method"])
        self.set_header("Access-Control-Allow-Origin", "*")

    def on_finish(self):
        self.user = None

0 个答案:

没有答案