web.py:如何使用404s有选择地隐藏任何HTTP方法的资源?

Ian*_*non 5 python http web.py

我想根据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()
Run Code Online (Sandbox Code Playgroud)

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

$ 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
...
Run Code Online (Sandbox Code Playgroud)

我可以对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
...
Run Code Online (Sandbox Code Playgroud)

有没有实现有蹊跷任何HTTP方法的web.py类中的所有方法中的一种方式,这样我就可以保证安全检查将运行?

或者是否有另一种隐藏这些资源的方法?

Ian*_*non 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))
        ...
Run Code Online (Sandbox Code Playgroud)

实例化:

app = application(urls, globals())
Run Code Online (Sandbox Code Playgroud)

页面类:

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

    def GET(self):
        ...
Run Code Online (Sandbox Code Playgroud)

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

            ...
            meth = web.ctx.method
            if meth == 'POST' and 'method' in web.input():
                meth = web.input()['method']
            ...
Run Code Online (Sandbox Code Playgroud)