2011-08-28 17 views
15

我目前正在用微框架Flask編寫一個rest python的Python。 這是一個私人API,它處理用戶數據。我打算使用這個API來構建一個Web和一個Android應用程序。尋求建議,以確保用python-flask編寫的私有REST API

現在我使用digest auth來保護私人用戶數據。例如,如果您想通過用戶bob在我的服務上發佈數據,請在myapi/story/create上發佈發佈請求,並使用摘要模式提供bob的憑證。

我知道這不是一個很好的解決方案,因爲:
-Digest身份驗證並不安全
-The客戶端沒有認證(?如何保證不與當前用戶相關的請求,例如創建一個新用戶)

我讀了很多關於oAuth的內容,但是三腳認證看起來有點矯枉過正,因爲我不打算將我的API打開到第三方。
雙腿oAuth不適合,因爲它只爲客戶提供認證,而不是爲用戶提供認證。
oAuth的另一個問題是,我還沒有找到在Python中實現它的全面指南。我找到python-oauth2庫,但我不明白服務器示例,我找不到其他文檔。另外,這個例子中沒有涉及oAuth的許多方面。

所以我的問題是:

  1. 是否有身份驗證的替代方案(未OAuth的)客戶端和用戶安全的一個合理的水平?
  2. 如果oAuth是最佳解決方案:
    • 如何跳過授權過程(因爲用戶不必授權第三方客戶端)?
    • python-oauth2或任何其他Python庫有詳細的文檔嗎?

任何幫助或建議,將不勝感激。

+0

至於你的問題之一,各大網站的很大一部分不會讓你通過客戶端等報名,他們讓你通過他們的網站註冊。對於那些允許這樣做的網站,他們的API調用與他們的註冊表單實際上是一樣的,所以不管它是否安全都沒關係。 –

回答

7

簡單的答案是通過HTTPS只會暴露你的API,然後使用HTTP基本身份驗證。我不認爲真的有任何理由打擾Digest。基本身份驗證是不安全的,但隨每個請求一起提交,因此您無需擔心身份驗證過期或其他問題。通過HTTPS隧道傳輸,您可以建立安全連接。

如果要驗證客戶端,可以使用SSL客戶端證書。也就是說,通常情況下,真正鎖定客戶端以防止惡意用戶非常困難,所以我會考慮讓註冊功能公開訪問,並通過帶外帳戶驗證來保護自己免受DOS等攻擊。

+1

我在業餘時間從事這個項目,不幸的是我停了下來。我用3腿oauth。實施起來並不容易,而且由於API是私有的,與Basic + https +客戶端證書相比,這些優勢顯着。我沒有嘗試,但你的回答是回答問題中最重要的部分(oAuth的替代),所以我將其標記爲接受。謝謝。 –

3

您是否已經考慮過使用基本身份驗證?

我還沒有使用你提到的框架,但我使用基本認證來保護基於web.py的應用程序中的一些URL,並且工作正常。

基本上,你可以在base64中使用一個標記,它實際上是一個標準的http heeader。

也許這個例子可以幫助你:

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 
+1

坦克爲您的答案,我感謝您的參與:)但基本或摘要身份驗證完全相同的問題。我如何在同一請求中驗證用戶和客戶端? –

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