5

我想根据 web.py 中的某种形式的身份验证有选择地隐藏一些资源,但是它们的存在是通过对我尚未实现的任何 HTTP 方法的 405 响应来揭示的。

这是一个例子:

import web

urls = (
    '/secret', 'secret',
    )

app = web.application(urls, globals())

class secret():
    def GET(self):
        if web.cookies().get('password') == 'secretpassword':
            return "Dastardly secret plans..."
        raise web.notfound()

if __name__ == "__main__":
    app.run()

当发出未定义的方法请求时,会显示资源:

$ curl -v -X DELETE http://localhost:8080/secret
...
> DELETE /secret HTTP/1.1
...
< HTTP/1.1 405 Method Not Allowed
< Content-Type: text/html
< Allow: GET
...

我可以对 HTTP 规范中的其他常用方法实施相同的检查,但有创意的恶棍可能会发明自己的方法:

$ curl -v -X SHENANIGANS http://localhost:8080/secret
...
> SHENANIGANS /secret HTTP/1.1
...
< HTTP/1.1 405 Method Not Allowed
< Content-Type: text/html
< Allow: GET
...

有没有办法在 web.py 类中为任何 HTTP 方法实现 catch all 方法,这样我就可以确保运行安全检查?

或者有没有其他方法可以隐藏这些资源?

4

3 回答 3

3

在 Daniel Kluev 的回答的启发下,我最终得出了web.application在方法中添加对默认方法的支持_delegate

import types

class application(web.application):
    def _delegate(self, f, fvars, args=[]):
        def handle_class(cls):
            meth = web.ctx.method
            if meth == 'HEAD' and not hasattr(cls, meth):
                meth = 'GET'
            if not hasattr(cls, meth):
                if hasattr(cls, '_default'):
                    tocall = getattr(cls(), '_default')
                    return tocall(*args)
                raise web.nomethod(cls)
            tocall = getattr(cls(), meth)
            return tocall(*args)

        def is_class(o): return isinstance(o, (types.ClassType, type))
        ...

实例化:

app = application(urls, globals())

页面类:

class secret():
    def _default(self):
        raise web.notfound()

    def GET(self):
        ...

我更喜欢这个解决方案,因为它可以保持页面类的整洁,并在一个地方提供对委派过程的进一步定制。例如,我想要的另一个功能是透明重载 POST(例如,将 POST 请求重定向method=DELETE到页面类的 DELETE 方法),在这里添加它也很简单:

            ...
            meth = web.ctx.method
            if meth == 'POST' and 'method' in web.input():
                meth = web.input()['method']
            ...
于 2010-08-05T14:58:13.137 回答
1

您可以像这样实现处理所有方法的方法:

class HelloType(type):
    """Metaclass is needed to fool hasattr(cls, method) check"""
    def __getattribute__(obj, name):
        try:
            return object.__getattribute__(obj, name)
        except AttributeError:
            return object.__getattribute__(obj, '_handle_unknown')        

class hello(object):
    __metaclass__ = HelloType
    def GET(self, *args, **kw):
        if web.cookies().get('password') == 'secretpassword':
            return "Dastardly secret plans..."
        raise web.notfound()

    def _handle_unknown(self, *args, **kw):
        """This method will be called for all requests, which have no defined method"""
        raise web.notfound()

    def __getattribute__(obj, name):
        try:
            return object.__getattribute__(obj, name)
        except AttributeError:
            return object.__getattribute__(obj, '_handle_unknown') 

__getattribute__由于 web.py 检查方法存在的方式,实现了两次:

def _delegate(self, f, fvars, args=[]):
    def handle_class(cls):
        meth = web.ctx.method
        if meth == 'HEAD' and not hasattr(cls, meth):
            meth = 'GET'
        if not hasattr(cls, meth): # Calls type's __getattribute__
            raise web.nomethod(cls)
        tocall = getattr(cls(), meth) # Calls instance's __getattribute__
于 2010-08-05T11:59:20.947 回答
0

您可以在“秘密”类中定义任何方法,例如 DELETE 或 SHENANIGAN,如下所示:

class secret():

    def DELETE(self):
       ...

    def SHENANIGANS(self):
       ...
于 2010-08-05T10:55:06.223 回答