2016-03-28 14 views
6

Tài liệu dành cho Flask-login nói về việc xử lý URL "tiếp theo". Ý tưởng này có vẻ là:Làm cách nào để chuyển qua URL "tiếp theo" với Flask và Flask-login?

  1. tài đi vào /some-secret-URL
  2. người dùng được chuyển hướng đến một trang đăng nhập (ví dụ /login)
  3. Sau khi đăng nhập thành công, người dùng sẽ được chuyển hướng trở lại /some-secret-URL

Ví dụ nửa đầy đủ chỉ sử dụng thông tin đăng nhập Flask mà tôi đã tìm thấy là https://gist.github.com/bkdinoop/6698956. Nó rất hữu ích, nhưng vì nó không bao gồm các tệp mẫu HTML, tôi thấy nếu tôi có thể tạo lại chúng như là một bài tập tự rèn luyện.

Dưới đây là một phiên bản đơn giản của phần /secret/login:

@app.route("/secret") 
@fresh_login_required 
def secret(): 
    return render_template("secret.html") 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    <...login-checking code omitted...> 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect(request.args.get("next") or url_for("index")) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 

Và đây là login.html:

<form name="loginform" action="{{ url_for('login') }}" method="POST"> 
Username: <input type="text" name="username" size="30" /><br /> 
Password: <input type="password" name="password" size="30" /><br /> 
<input type="submit" value="Login" /><br /> 

Bây giờ, khi người dùng truy cập /some-secret-URL, ông được chuyển hướng đến /login?next=%2Fsecret. Cho đến nay, rất tốt - tham số "tiếp theo" nằm trong chuỗi truy vấn.

Tuy nhiên, khi người dùng gửi biểu mẫu đăng nhập, anh ta được chuyển hướng trở lại trang chỉ mục, chứ không phải quay lại URL /secret.

Tôi đoán lý do là vì thông số "tiếp theo" có sẵn trên URL đến, không được tích hợp vào biểu mẫu đăng nhập và do đó không được chuyển thành biến khi biểu mẫu được xử lý. ? đúng cách để giải quyết việc này

Một giải pháp dường như làm việc - thay đổi thẻ <form> từ

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

tới:

<form name="loginform" method="POST"> 

Với thuộc tính "action" bị loại bỏ, trình duyệt (ít nhất Firefox 45 trên Windows) tự động sử dụng URL hiện tại, khiến nó kế thừa chuỗi truy vấn ?next=%2Fsecret, thành công gửi nó tới trình xử lý biểu mẫu.

Nhưng bỏ qua thuộc tính biểu mẫu "hành động" và để trình duyệt điền vào đúng giải pháp? Nó có hoạt động trên tất cả các trình duyệt và nền tảng không?

Hoặc Flask hoặc Flask-login có ý định xử lý theo cách khác không?

+0

đầu ra trong nguồn của html khi bạn đặt 'action =" {{url_for ('login')}} "' là gì? –

+0

http://flask.pocoo.org/snippets/63/ – davidism

+0

@K DawG, nó là '

' –

Trả lời

4

Nếu bạn cần chỉ định thuộc tính hành động khác trong biểu mẫu của mình, bạn không thể sử dụng thông số tiếp theo do Flask-Login cung cấp. Tôi muốn đề nghị anyways để đặt điểm cuối thay vì url vào tham số url vì nó được dễ dàng hơn để xác nhận. Dưới đây là một số mã từ ứng dụng tôi đang làm việc, có thể điều này có thể giúp bạn.xử lý trái phép

Overwrite Flask-Đăng nhập để sử dụng các thiết bị đầu cuối thay vì url trong tham số tiếp theo:

@login_manager.unauthorized_handler 
def handle_needs_login(): 
    flash("You have to be logged in to access this page.") 
    return redirect(url_for('account.login', next=request.endpoint)) 

Sử dụng request.endpoint trong URL của riêng bạn quá:

{# login form #} 
<form action="{{ url_for('account.login', next=request.endpoint) }}" method="post"> 
... 
</form> 

Redirect đến thiết bị đầu cuối trong tham số tiếp theo nếu nó tồn tại và hợp lệ, chuyển hướng khác đến dự phòng.

def redirect_dest(fallback): 
    dest = request.args.get('next') 
    try: 
     dest_url = url_for(dest) 
    except: 
     return redirect(fallback) 
    return redirect(dest_url) 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    ... 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect_dest(fallback=url_for('general.index')) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 
+0

Trong biểu mẫu tôi sử dụng: next = request.args.get ("next"). Cũng trong redirect_dest nó có thể là dest = request.args.get ("next") – 2ni

+0

@ 2ni Trong ví dụ của tôi, biểu mẫu được hiển thị trên đầu mỗi trang, nếu bạn muốn một trang đăng nhập riêng, bạn nên sử dụng 'next = request. args.get ("tiếp theo") '. Đã sửa lỗi đề cập thứ hai của bạn, cảm ơn. – timakro

0

@timakro cung cấp giải pháp gọn gàng. Nếu bạn muốn xử lý một liên kết động như

index/< dùng >

sau đó sử dụng request.path thay vì request.endpoint sẽ không chứa các thông tin vairable động:

@login_manager.unauthorized_handler 
def handle_needs_login(): 
    flash("You have to be logged in to access this page.") 
    return redirect(url_for('account.login', next=request.path)) 

mã sau đây phải được đổi thành:

def redirect_dest(home): 
    dest_url = request.args.get('next') 
    if not dest_url: 
     dest_url = url_for(home) 
    return redirect(dest_url) 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    ... 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect_dest(home=anyViewFunctionYouWantToSendUser) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 
Các vấn đề liên quan