寻求建议以保护用 python-flask 编写的私有 REST API
Posted
技术标签:
【中文标题】寻求建议以保护用 python-flask 编写的私有 REST API【英文标题】:Looking for advice to secure a private REST API written in python-flask 【发布时间】:2011-11-05 16:19:04 【问题描述】:我目前正在使用微框架 Flask 在 python 中编写一个 rest API。 这是一个私有 API,它处理用户数据。我打算使用这个 API 来构建一个 Web 和一个 android 应用程序。
现在我使用摘要身份验证来保护私人用户数据。例如,如果您想通过用户 bob 在我的服务上发布数据,您可以在 myapi/story/create 发出发布请求,并使用摘要模式提供 bob 的凭据。
我知道这不是一个好的解决方案,因为: -摘要式身份验证不安全 - 客户端未通过身份验证(如何保护与当前用户无关的请求,例如创建新用户?)
我阅读了很多关于 oAuth 的资料,但 3-legged 身份验证似乎有点矫枉过正,因为我不打算向第三方开放我的 API。 2-legged oAuth 不适合,因为它只为客户提供身份验证,而不为用户提供身份验证。 oAuth 的另一个问题是我还没有找到在 Python 中实现它的综合指南。我找到了python-oauth2 库,但我不了解服务器示例,也找不到其他文档。另外,这个示例似乎没有涵盖 oAuth 的许多方面。
所以我的问题是:
-
是否有替代方案(不是 oAuth)以合理的安全级别对客户端和用户进行身份验证?
如果 oAuth 是最佳解决方案:
如何跳过授权过程(因为用户不必授权第三方客户端)?
是否有关于 python-oauth2 或任何其他 Python 库的详细文档?
我们将不胜感激任何帮助或建议。
【问题讨论】:
关于你的一个问题,很大一部分主要网站不让你通过客户端等注册,他们让你通过他们的网站注册。对于那些允许这样做的网站,他们的 API 调用实际上与他们的注册表单是一样的,所以它是否安全并不重要。 【参考方案1】:如果您对基本身份验证感兴趣,这里有一个快速属性,您可以使用它来装饰您的处理程序http://www.varunpant.com/posts/basic-authentication-in-web-py-via-attribute。这个例子主要是在 web.py 上下文中编写的,但我想它可以很容易地调整。
def check_auth(username, password):
return username == 'username' and password == 'password'
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = web.ctx.env['HTTP_AUTHORIZATION'] if 'HTTP_AUTHORIZATION' in web.ctx.env else None
if auth:
auth = re.sub('^Basic ', '', auth)
username, password = base64.decodestring(auth).split(':')
if not auth or not check_auth(username, password):
web.header('WWW-Authenticate', 'Basic realm="admin"')
web.ctx.status = '401 Unauthorized'
return
return f(*args, **kwargs)
return decorated
【讨论】:
【参考方案2】:简单的答案是仅通过 HTTPS 公开您的 API,然后使用 HTTP 基本身份验证。我认为没有任何理由打扰 Digest。基本身份验证是不安全的,但会随每个请求一起提交,因此您无需担心身份验证会过时或其他任何情况。通过 HTTPS 建立隧道,您就拥有了安全的连接。
如果您想对客户端进行身份验证,您可以使用 SSL 客户端证书。也就是说,一般来说,真正锁定客户端以防止恶意用户非常困难,所以我会考虑让注册功能公开访问,并通过带外帐户验证保护自己免受 DOS 等攻击。
【讨论】:
我在业余时间从事这个项目,不幸的是我停止了它。我使用了 oauth 3-legged。这并不容易实现,而且由于 API 是私有的,因此与 Basic + https + 客户端证书相比没有显着的好处。我没有尝试过,但您的回答回应了问题的最重要部分(替代 oAuth),因此我将其标记为已接受。谢谢。【参考方案3】:您是否已经考虑过使用基本身份验证?
我还没有使用你提到的框架,但是我使用了基本的身份验证来保护基于 web.py 的应用中的一些 url,并且工作正常。
基本上,您可以使用 base64 中的令牌,它实际上是一个标准的 http 标头。
也许这个例子可以帮助你:
class Login:
def GET(self):
auth = web.ctx.env.get('HTTP_AUTHORIZATION')
authreq = False
if auth is None:
authreq = True
else:
auth = re.sub('^Basic ','',auth)
username,password = base64.decodestring(auth).split(':')
if (username,password) in settings.allowed:
raise web.seeother('/eai')
else:
authreq = True
if authreq:
web.header('WWW-Authenticate','Basic realm="Auth example"')
web.ctx.status = '401 Unauthorized'
return
【讨论】:
感谢您的回答,感谢您的参与 :) 但基本或摘要身份验证存在完全相同的问题。如何在同一个请求中对用户和客户端进行身份验证?以上是关于寻求建议以保护用 python-flask 编写的私有 REST API的主要内容,如果未能解决你的问题,请参考以下文章
编写高质量代码改善C#程序的157个建议——建议49:在Dispose模式中应提取一个受保护的虚方法