龙卷风拦截器 - 空响应

时间:2014-07-14 08:04:25

标签: python tornado interceptor

我正在使用拦截器检查龙卷风应用程序中用户传递的令牌的有效性。

def token_authenticate():
    def wrapper(self, transforms, *args, **kwargs):
        def _throw_error(self):
            print 'writing basic auth'
            if self._headers_written:
                raise Exception('headers have already been written')
            self.write(json.dumps({'auth': 'false'}))
            self.finish()
            return False

        request = self.request
        try:
            token = request.arguments.get('token')[0]
            if not token:
                return _throw_error(self)

            session = Instance().get_session()

            user_token = session.query(UserToken)\
                .filter(UserToken.token == token)\
                .filter(UserToken.expires > datetime.utcnow())\
                .one()

            if user_token:
                self.token = user_token
                self.user = user_token.user

            else:
                print 'no user token'
                return _throw_error(self)
        except Exception, e:
            print 'exception ' + e
            return _throw_error(self)
        return True

    return wrapper

def interceptor(func):
    def classwrapper(cls):
        def wrapper(old):
            def inner(self, transforms, *args, **kwargs):
                log.debug('Invoking wrapper %s', func)
                ret = func(self, transforms, *args, **kwargs)
                if ret:
                    return old(self, transforms, *args, **kwargs)
                else:
                    return ret

            return inner

        cls._execute = wrapper(cls._execute)
        return cls

    return classwrapper

## HANDLER
@interceptor(token_authenticate())
class SampleAuthenticatedRequestHandler(BaseHandler):
    def get(self):
        self.write({'response': self.user.as_dict()})

当令牌丢失/无效时,请求会收到空响应。

> curl localhost:8888/test -I -v
* Adding handle: conn: 0x7fb18b004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fb18b004000) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 8888 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 8888 (#0)
> HEAD /test HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8888
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server

有什么遗失的吗?这是从我的处理程序中抽象身份验证的最佳方法吗?我希望能够为不同类型的身份验证复制此模型(基于令牌,基于会话等)。

2 个答案:

答案 0 :(得分:0)

RequestHandler._execute是一个内部方法,这将在Tornado 4.0中破解。 prepare()和HTTP谓词方法get() / post() / etc是在子类中重写的受支持方法。虽然服务器日志(你没有发布)可能有一些有用的东西,但是我没有看到这个代码会返回空响​​应的任何理由。

答案 1 :(得分:0)

这是上述功能的工作版本。只是为了遇到同样麻烦的其他人 -

def token_authenticate():
    """
    This is a basic authentication interceptor which
    protects the desired URIs and requires
    authentication as per configuration
    """

    def wrapper(self, transforms, *args, **kwargs):

        request = self.request
        try:
            token = request.arguments.get('token')[0]
            if not token:
                return False

            user_token = get_user(token)

            if user_token:
                self.token = user_token
                self.user = user_token.user
                return True
        except:
            pass
        return False

    return wrapper


def interceptor(func):
    """
    This is a class decorator which is helpful in configuring
    one or more interceptors which are able to intercept, inspect,
    process and approve or reject further processing of the request
    """

    def classwrapper(cls):
        def wrapper(old):
            def inner(self, transforms, *args, **kwargs):
                ret = func(self, transforms, *args, **kwargs)
                if ret:
                    return old(self, transforms, *args, **kwargs)
                else:
                    self._transforms = transforms
                    return self._unauthorized()

            return inner

        cls._execute = wrapper(cls._execute)
        return cls

    return classwrapper