寻找保护用python-flask编写的私有REST API的建议

15 投票
3 回答
7934 浏览
提问于 2025-04-17 00:30

我现在正在用Python的微框架Flask写一个REST API。这个API是私有的,主要处理用户数据。我打算用这个API来开发一个网页和一个安卓应用。

目前我使用的是摘要认证来保护用户的私密数据。比如,如果你想用用户bob的身份在我的服务上发布数据,你就需要向我的接口myapi/story/create发送一个POST请求,并提供bob的认证信息。

我知道这种方法并不好,因为:
- 摘要认证并不安全
- 客户端没有经过认证(如何保护与当前用户无关的请求,比如创建一个新用户?)

我读了很多关于oAuth的资料,但三方认证似乎有点过于复杂,因为我不打算把我的API开放给第三方。
而二方oAuth也不适用,因为它只提供客户端的认证,而不涉及用户的认证。
另外一个问题是,我没有找到关于如何在Python中实现oAuth的详细指南。我找到了一些python-oauth2库,但我不太理解服务器的示例,也找不到额外的文档。而且这个示例似乎没有涵盖oAuth的许多方面。

所以我有几个问题:

  1. 有没有其他方案(不是oAuth)可以合理地同时认证客户端和用户,并且安全性还不错?
  2. 如果oAuth是最好的解决方案:
    • 如何跳过授权过程(因为用户不需要授权第三方客户端)?
    • 有没有关于python-oauth2或其他Python库的详细文档?

任何帮助或建议都非常感谢。

3 个回答

0

如果你对基本的身份验证感兴趣,这里有一个简单的属性,可以用来装饰你的处理器。你可以查看这个链接了解更多信息: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
4

你有没有考虑过使用基本认证呢?

我还没有用过你提到的那个框架,但我在一个基于web.py的应用中使用过基本认证来保护一些网址,效果很好。

基本上,你可以使用一个用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
8

简单来说,就是只通过HTTPS来提供你的API,然后使用HTTP基本认证。我觉得没有必要去使用Digest认证。基本认证虽然不太安全,但每次请求都会提交,所以你不需要担心认证过期或者其他问题。通过HTTPS来传输,这样就能保证连接的安全。

如果你想验证客户端身份,可以使用SSL客户端证书。不过一般来说,真正保护客户端不被恶意用户攻击是比较困难的,所以我建议让注册功能开放访问,同时通过其他方式来验证账户,保护自己免受拒绝服务攻击等问题。

撰写回答