2013-11-25 2 views
7

私たちは職場でFlask + Jinja2でWebアプリケーションを作成しています。 アプリケーションには、ロールに基づいて特定のページにアクセスできるユーザーが登録されています。Jinja2テンプレートのアクセスできないリンクを隠す

@app.route('/action1') 
@security_requirements(roles=['some_role']) 
def action1(): 
    ... 

デコレータチェックを飾った関数の呼び出しを渡すかどうか、ログオンしたユーザーの役割リストに「some_role」を持っていると判断した場合:サーバー側でこれを達成するために私達はちょうどページを飾る使用しますユーザーを「アクセスが拒否されました」ページにリダイレクトするだけです。

アプリケーションには、ブートストラップを使用して実装されたナビゲーションバーもあります。ナビゲーションバーは、基本テンプレートを使用して各ページに表示されます。現時点では、アプリケーションのすべてのページは、現在のユーザーがアクセスできるかどうかにかかわらず、ナビゲーションバーにエントリがあります。セキュリティホールではないにもかかわらず、アクセスできないユーザーページから隠したいと思っています。さらに、Jinjaテンプレート内の許可されたロールリストを複製することなく、この機能を実現したいと考えています。 Jinjaでこの機能を実現するには、現在のデコレータを使用することができますか?

+1

あなたのデコレータは 'security_requirements'ですか?それを変更することは許可されていますか? – twil

+0

@twil - はい、それは私のものです – reish

答えて

1

から来て、私はこのように見てsecurity_requirementsデコレータを変更:

def security_requirements(logged_in=True, 
          roles=None): 
def wrapper(f): 
    # Store the security attributes as a member of the function object 
    f.access_control = dict(logged_in=logged_in, roles=roles) 
    @functools.wraps(f) 
    def wrapped(*args, **kwargs): 
     access_result = _eval_access(logged_in, roles) 
     # Redirect the user to the appropriate page (Access denied/Login Required/Actual Page) based on the result 
     ... 

このデコレータの以前のバージョンとの実際の違いは、セキュリティ属性を関数オブジェクト内に格納する行だけです。この行はデコレータの内側からは無用です。しかし、今、私は神社のテンプレートから呼ばれるように、次のアクションを実装することができます

{% if can_access(func) %} 
<li><a>...</a></li> 
{% endif %} 

can_access機能は、フラスコのアプリケーションモジュールで定義されています。関数オブジェクトに変換する必要がある文字列を受け取ります。

def can_access(func): 
    return auth.can_access(app.view_functions[func]) 

この機能神社テンプレートから直接呼び出すべきである:それは、app.view_functionsを呼び出していることを行います。だから、神社のグローバルに追加する必要があります

app.jinja_env.globals.update(can_access=can_access) 
最後に

auth.can_accessを: - 関数デコレータです

def can_access(f): 
    if not hasattr(f, 'access_control'): 
     return True 

    # Use the access_control member set by the decorator 
    return _eval_access(**f.access_control) == AccessResult.ALLOWED 

このソリューションでは、アクセス制御が1つの場所で定義されていることを意味します。

+0

私はこれを完全に理解していませんが、素敵です! – 8oh8

+0

これはパッチとして提出する必要があります。これは素晴らしい機能です。 – Plasma

5

私はFlask-Securityを使用します。これは、多くのログイン/セキュリティモジュールを素敵なパッケージに結びつけています。それはあなたがすることができますフラスコ-校長の役割管理礼儀、付属しています:

{% if current_user.has_role('admin') %} 
    <li><a href="#">Manage Site</a></li> 
{% endif %} 

あなたができるsee how that's implemented in the sourcecurrent_userプロキシがFlask-Login

+0

私は、各アクションに許可されているロールのリストを格納するために単一の場所を使いたいと思います。私が正しく理解していれば、Flask-Securityであっても、サーバーサイドのコードとテンプレートの内部に、それぞれのアクションごとに2つのリストを書く必要があります。 – reish

+0

それでは、{%if current_user.can_access(url_for( 'protected_endpoint'))%} ADMIN ONLY {%endif%} 'のようなことをしようとしていますか? – Doobeh

+0

はい、まさに:) – reish

関連する問題