2013-12-23 260 views
1

我在我的應用程序中使用Flask登錄的@login_required裝飾器的一些路線。在未登錄的情況下導航到這些路線時,我被重定向到登錄頁面。到現在爲止還挺好。login_required編碼的下一個參數,重定向失敗

重定向的URL看起來是這樣的:/login?next=%2Fusers
看起來它的URL編碼的下一個參數,這是我沒有在我已經運行在整個實施例中看到。登錄後重定向回到next總是失敗並回退到索引頁面。我認爲這是因爲next是網址編碼的。

我應該以這種不同的方式進行研究嗎?我只是開始深入Flask框架並開始使用示例,所以我不太瞭解執行任務的最佳方法。

下面是一個例子路線:

login_manager.login_view = 'login' 

@app.route('users') 
@login_required 
def users(): 
    return 'Test' 

我的登錄路由看起來是這樣的:在您的幫助

@app.route('/login') 
def login(): 
    error = None 
    next = request.args.get('next') 
    if request.method == 'POST': 
    username = request.form['username'] 
    password = request.form['password'] 

    if authenticate_user(username, password): 
     user = User.query.filter_by(username=username).first() 
     if login_user(user): 
     flash("You have logged in") 
     session['logged_in'] = True 
     return redirect(next or url_for('index', error=error)) 
    error = "Login failed" 
    return render_template('login.html', login=True, next=next, error=error) 

感謝。

+1

注意,這暴露了一個安全漏洞:如果我送你像'/登錄下一=的http%3A%的鏈接? 2F%2Fbadsite.com%2F',您將在登錄後將用戶重定向到該外部頁面,這將要求他們「重新登錄」並獲取其密碼。令人遺憾的是,當談到認證和類似的樣板代碼時,Flask真的很缺乏。 – Blender

+0

是的,檢查是否也在待辦事項列表中,我現在只是在處理嬰兒的步驟。 –

+0

真正的問題是表單模板的操作字段。它看起來像重定向處理編碼路徑沒有任何問題。 –

回答

3

我想通了,導航到一個需要登錄的路徑(/在這個例子中請求)會導致重定向到登錄頁面與next參數。

/login?next=%2Frequests 

在我登錄的模板,我有這樣的:

<form action="{{ url_for('login') }}" method='POST'> 

這引起了形式發佈到/login路線不帶任何參數。刪除action屬性或將其更改爲action=""會導致將表單發佈到其自己的url,其中包含原始查詢字符串。另一個選項是在url_for中包含next=next

<form action="{{ url_for('login', next=next) }}" method='POST'> 
0

在這裏你去:

import urllib 


@app.route('/login') 
def login(): 
    error = None 
    next = urllib.unquote_plus(request.args.get('next')) 
    ... 
+0

這是在Flask中使用它的推薦方式嗎? –

+0

我從來沒有見過一種「推薦」的方式,因爲Flask爲您提供了實現它的靈活性,不過您喜歡...將URL保存在會話/ cookie中,並將其作爲參數傳遞給URL等。 個人,我會使用會話,因爲它不太可能被用戶篡改。 – iandouglas

+0

URL參數在您訪問它們時已被解碼,因此沒有理由將其解碼兩次。 – Blender

0

如果有人發現像我這樣的問題,這裏是爲我工作的實現。問題在於登錄的POST表單只會進入/ login,導致下一個URL被拋棄。按照Kevan的建議,如果您將next=request.args.get('next'))添加到登錄表單的操作中,它將會傳遞下一個參數。

在我的登錄功能

@app.route('/login', methods = ['GET', 'POST']) 
def login(): 
    next = request.args.get('next') 
    if request.method == 'POST': 
     ...Confirm User... 
      if next: 
       return redirect(next) 
      else: 
       return redirect('/') 

在我的登錄表單

<form method="post" action="{{ url_for('login', next=request.args.get('next')) }}" enctype="multipart/form-data">