2010-08-01 26 views
6

Tôi muốn ẩn có chọn lọc một số tài nguyên dựa trên một số hình thức xác thực trong web.py, nhưng sự tồn tại của chúng được tiết lộ bởi 405 câu trả lời cho bất kỳ phương thức HTTP nào mà tôi chưa triển khai.web.py: Cách chọn lọc ẩn tài nguyên với 404 cho bất kỳ phương thức HTTP nào?

Dưới đây là một ví dụ:

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() 

Khi một yêu cầu phương pháp xác định được ban hành, các tài nguyên được tiết lộ:

$ 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 
... 

tôi có thể thực hiện việc kiểm tra tương tự cho các phương pháp phổ biến khác trong đặc tả HTTP , nhưng một miscreant sáng tạo có thể phát minh ra của riêng mình:

$ 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 
... 

Is có một cách để thực hiện một phương pháp bắt tất cả trong một lớp web.py cho bất kỳ phương thức HTTP nào, vì vậy tôi có thể đảm bảo kiểm tra bảo mật sẽ được chạy?

Hoặc có cách nào khác để ẩn các tài nguyên này không?

Trả lời

4

soi sáng bởi câu trả lời Daniel Kluev, tôi đã kết thúc phát sinh từ web.application để hỗ trợ thêm cho một phương pháp mặc định trong _delegate phương pháp:

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()) 

lớp Page:

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

    def GET(self): 
     ... 

Tôi thích giải pháp này bởi vì nó giữ cho các lớp trang sạch sẽ và dành thêm sự tùy biến của quá trình ủy nhiệm ở một nơi duy nhất. Ví dụ, một tính năng gì tôi muốn là minh bạch POST quá tải (ví dụ như chuyển hướng một yêu cầu POST với method=DELETE với phương pháp DELETE của lớp trang.) Và nó đơn giản để thêm rằng đây quá:

  ... 
      meth = web.ctx.method 
      if meth == 'POST' and 'method' in web.input(): 
       meth = web.input()['method'] 
      ... 
0

bạn có thể xác định bất kỳ phương thức trong lớp 'bí mật' của bạn, chẳng hạn như DELETE hoặc tinh quái, như thế này:

class secret(): 

    def DELETE(self): 
     ... 

    def SHENANIGANS(self): 
     ... 
+1

Kẻ tấn công có thể phát minh ra bất cứ điều gì phương pháp tên họ thích. Nếu tôi bắt đầu xác định các phương pháp cho mọi khả năng tôi sẽ bỏ lỡ hạn chót của mình :) –

1

Bạn có thể thực hiện phương pháp xử lý-all-phương pháp như thế này:

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__ được triển khai hai lần do cách web.py kiểm tra sự tồn tại của phương thức:

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__ 
+0

Cảm ơn rất nhiều vì lời giải thích rõ ràng và hữu ích này. Tôi quyết định sử dụng một phương pháp khác mà tôi cảm thấy thoải mái hơn, nhưng tôi không biết bắt đầu từ đâu trước khi đọc câu trả lời của bạn! –

Các vấn đề liên quan