2016-03-28 8 views
6

Flask-loginのドキュメントでは、「次の」URLの処理について説明しています。アイデアがあると思われる:ユーザーがログインページにリダイレクトされ FlaskとFlask-loginで「次の」URLをどのように通すのですか?

  • /some-secret-URL

    1. ユーザーが行く(例えば/login
    2. は、ログインに成功した後、ユーザーは/some-secret-URL
    に戻ってリダイレクトされます

    私が見つけたFlask-loginを使用している唯一の例は、https://gist.github.com/bkdinoop/6698956です。これは役に立ちますが、HTMLテンプレートファイルが含まれていないため、自己練習として再作成できるかどうかを確認しています。

    はここ/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") 
    

    そして、ここで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 /> 
    

    、ユーザーの訪問/some-secret-URLが、彼は/login?next=%2Fsecretにリダイレクトされますとき。これまでのところ、「次の」パラメータはクエリ文字列内にあります。

    ユーザーがログインフォームを送信すると、ユーザーは/secret URLに戻るのではなく、インデックスページにリダイレクトされます。

    私は、着信URLで利用可能だった「次の」パラメータがログインフォームに組み込まれていないため、フォームが処理されるときに変数として渡されないためだと推測しています。これを解決する正しい方法

    一つの解決策は、動作しているようです - に

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

    から<form>タグを変更します?

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

    "action"属性を削除すると、ブラウザ(Windowsでは少なくともFirefox 45)が自動的に現在のURLを使用し、?next=%2Fsecretというクエリ文字列を継承し、フォーム処理ハンドラに正常に送信されます。

    「アクション」フォームの属性を省略し、ブラウザで適切なソリューションに入力させるようにしていますか?それはすべてのブラウザとプラットフォームで機能しますか?

    また、FlaskまたはFlask-loginはこれを別の方法で処理する予定ですか?

  • +0

    'action =" {{url_for( 'login')}} ''を実行すると、htmlのソースの出力はどうなりますか? –

    +0

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

    +0

    @K DawG、それは '

    ' –

    答えて

    4

    フォーム内に異なるアクションアトリビュートを指定する必要がある場合は、Flask-Loginが提供する次のパラメータを使用できません。 URLの代わりにエンドポイントをurlパラメータに入れることをお勧めします。これは、検証が簡単なためです。ここに私が取り組んでいるアプリケーションのコードがありますが、これはあなたを助けるかもしれません。エンドポイントでの

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

    リダイレクト:

    @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)) 
    
    あまりにも独自のURLで

    使用request.endpoint

    上書きフラスコ-ログインの不正なハンドラは次のパラメータで、URLの代わりにエンドポイントを使用するにはそれが存在し、有効な場合は次のパラメータ、それ以外の場合はフォールバックにリダイレクトします。

    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

    私は以下のフォームを使用します:next = request.args.get( "next")。また、redirect_destにはおそらくdest = request.args.get( "next") – 2ni

    +0

    @ 2niであるべきです。私の例では、フォームはすべてのページの上に表示されます。別のログインページが必要な場合は、 'next = request。 args.get( "next") '。あなたの2番目の言及を修正しました。 – timakro

    0

    @timakroはきちんとした解決策を提供します。 あなたはrequest.endpointがダイナミックvairable情報は含まれませんので、このような

    インデックス/ <ユーザーの代わりにrequest.pathを使用して、その後>

    などの動的リンクを処理する場合:

    @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)) 
    

    次のコードは、

    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") 
    
    に変更されます。
    関連する問題