用于GAE Web服务安全检查的Python装饰器 [英] Python Decorator for GAE Web-Service Security Check

查看:90
本文介绍了用于GAE Web服务安全检查的Python装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这篇文章中,Nick提出了一个decoartor:

Python / WebApp Google App Engine - 为用户测试/传递头文件



我正在编写一个API来公开潜在的数十种方法作为Web服务,所以装饰器听起来像个好主意。

我试图根据此示例开始编码:
http://groups.google.com/group/google-appengine/browse_thread/thread/ac51cc32196d62f8/aa6ccd47f217cb9a? lnk = gst& q = timeout#aa6ccd47f217cb9a

我需要它与Python 2.5兼容才能在Google App Engine(GAE)下运行。



这是我的尝试。如果我在正确的轨道上,请指出方向。
当前在这一行出现错误Invalid Syntax:
class WSTest(webapp.RequestHandler):

我的想法是传递一个数组角色的装饰者。这些是唯一的角色(从我的数据库应该有权访问每个不同的Web服务)。

  def BasicAuthentication(roles = []):
def _decorator(func):
def _wrapper * args,** kwds):
logging.info(\\\
\\\
BasicAuthentication:START:__ call__ \\\
\\\

auth = None
if'Authorization 'in self.request.headers:
auth = self.request.headers ['Authorization']
如果不是auth:
self.response.headers ['WWW-Authenticate'] =' Basic realm =MYREALM'
self.response.set_status(401)
self.response.out.write(需要授权)
logging.info(\\\
\ n需要授权\\\
\\\

返回

(用户名,密码)= base64.b64decode(auth.split('')[1])。split(': ')
logging.info(\\\
\\\
username =+ username +password =+ password +\\\
\\\


isValidUserPass = False
U sersSimulatedRole =Admin
#check针对数据库在这里...
如果用户==test12和密码==test34:
isValidUserPass = True
isValidRole = False
如果usersSimulatedRole在角色中:
isValidRole = True
#next检查用户是否具有其中一个角色
#TODO

如果不是isValidUserPass:
self.response.set_status(403)
self.response.out.write(Forbidden:Userid / password combination failed)

logging.info(\\\
\ n BasicAuthentication:END:__ call__ \\\
\\\

返回func(* args,** kwds)
返回_wrapper
返回_decorator


@BasicAuthentication([Admin,Worker])#可以运行此函数的角色
class WSTest(webapp.RequestHandler):
def get(self):
logging.info(\\\
\\\
\\\
WSTest \\\
\\\

... etc ...

谢谢,
Neal Walters

解决方案

你需要编写一个方法装饰器,而不是类装饰器:正如lost-theory指出的那样,Python 2.5中不存在类装饰器,并且在任何情况下它们都不能很好地工作,因为RequestHandler类没有使用请求数据进行初始化,直到构建它之后的。方法装饰器也给了你更多的控制 - 例如,你可以允许未请求的GET请求,但仍然需要对POST请求进行验证。

除此之外,你的装饰器看起来很好 - 只是将其应用于相关方法。我真正建议的唯一更改是用.error()调用替换.set_status()调用并除去response.write调用;这允许你重写RequestHandler类的.error(),为每个可能的状态码输出一个不错的错误页面。


In this post, Nick suggested a decoartor:

Python/WebApp Google App Engine - testing for user/pass in the headers

I'm writing an API to expose potentially dozens of methods as web-services, so the decorator sounds like a great idea.

I tried to start coding one based on this sample: http://groups.google.com/group/google-appengine/browse_thread/thread/ac51cc32196d62f8/aa6ccd47f217cb9a?lnk=gst&q=timeout#aa6ccd47f217cb9a

I need it compatible with Python 2.5 to run under Google App Engine (GAE).

Here's my attempt. Please just point the way to if I'm on the right track or not. Currently getting an error "Invalid Syntax" on this line: class WSTest(webapp.RequestHandler):

My idea is to pass an array of roles to the decorator. These are the only roles (from my db that should have access to each various web service).

def BasicAuthentication(roles=[]):
  def _decorator(func):
    def _wrapper(*args, **kwds): 
        logging.info("\n\n BasicAuthentication:START:__call__ \n\n") 
        auth = None 
        if 'Authorization' in self.request.headers: 
           auth = self.request.headers['Authorization']
        if not auth:
           self.response.headers['WWW-Authenticate'] = 'Basic realm="MYREALM"'
           self.response.set_status(401)
           self.response.out.write("Authorization required")
           logging.info ("\n\n  Authorization required \n\n") 
           return 

        (username, password) = base64.b64decode(auth.split(' ')[1]).split(':')
        logging.info ("\n\n username = " + username + "  password=" + password + "\n\n")         

        isValidUserPass = False 
        usersSimulatedRole = "Admin" 
        #check against database here...  
        if user == "test12" and password == "test34":
           isValidUserPass = True  
        isValidRole = False 
        if usersSimulatedRole in roles:
           isValidRole = True 
        #next check that user has one of the roles 
        #  TODO 

        if not isValidUserPass:
           self.response.set_status(403)
           self.response.out.write("Forbidden: Userid/password combination failed")

        logging.info("\n\n BasicAuthentication:END:__call__ \n\n") 
        return func(*args, **kwds) 
    return _wrapper
  return _decorator 


@BasicAuthentication(["Admin","Worker"])   #list of roles that can run this function 
class WSTest(webapp.RequestHandler):
  def get(self):
     logging.info("\n\n\n WSTest \n\n") 
     ...etc...

Thanks, Neal Walters

解决方案

You need to write a method decorator, not a class decorator: As lost-theory points out, class decorators don't exist in Python 2.5, and they wouldn't work very well in any case, because the RequestHandler class isn't initialized with request data until after it's constructed. A method decorator also gives you more control - eg, you could allow GET requests unauthenticated, but still require authentication for POST requests.

Other than that, your decorator looks fine - just apply it to the relevant methods. The only change I would really suggest is replacing the .set_status() calls with .error() calls and remove the response.write calls; this allows you to override .error() on the RequestHandler class to output a nice error page for each possible status code.

这篇关于用于GAE Web服务安全检查的Python装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆