2015-10-02 115 views
1

在我的網站上,除了某些特定頁面(登錄,註冊,pwd重置)以外,用戶需要登錄。我已經實現了remember me功能,它運行良好。Symfony2具有多重角色要求的訪問控制

我想實現的是,對於管理頁面,用戶應該有admin role and not remembered。爲了檢查這個要求,我在相關的access_control規則中使用了allow_if,但是它拒絕我的管理員用戶的訪問,儘管會話不被記住,並且我可以確認會話在調試工具欄上有UsernamePasswordToken

我ACCESS_CONTROL規則如下:(4日一個不工作

access_control: 
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/user/register, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/user/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/admin, allow_if: "has_role('ROLE_ADMIN') and has_role('IS_AUTHENTICATED_FULLY')" } 
    - { path: ^/, role: IS_AUTHENTICATED_REMEMBERED } 

如果我從相應的訪問控制規則中刪除and has_role('IS_AUTHENTICATED_FULLY')部分,用戶可以通過授權,所以這個問題似乎是這部分。

has_role('IS_AUTHENTICATED_FULLY')有什麼問題?

Symfony的版本:2.7.5

+0

是什麼探查說?您的特定用戶是否具有「IS_AUTHENTICATED_FULLY」或「IS_AUTHENTICATED_REMEMBERED」角色?完全是隻有當這個特定的會話期間用戶提供商的用戶名和密碼。 –

+0

正如我在問題上所述,我可以驗證我的會話有'UsernamePasswordToken'。如果它是一個記住的會話,它將是'RememberMeToken'。 – Lashae

回答

0

好執行授權在控制器檢查,我找到了一個解決方法來解決這個問題。官方網站

How to use Expressions in Security, Routing, Services, and Validation菜譜文章有相關的部分,並指出可能使用is_remember_me()is_fully_authenticated()方法檢查是否存在IS_AUTHENTICATED_REMEMBEREDIS_AUTHENTICATED_FULLY角色各自的。

is_remember_me比檢查IS_AUTHENTICATED_REMEMBERED

的is_remember_me和is_authenticated_fully功能類似於使用IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_FULLY與isGranted功能不同 - 但它們是不一樣的。下面顯示的區別:

use Symfony\Component\ExpressionLanguage\Expression; 
// ... 

$ac = $this->get('security.authorization_checker'); 
$access1 = $ac->isGranted('IS_AUTHENTICATED_REMEMBERED'); 

$access2 = $ac->isGranted(new Expression(
'is_remember_me() or is_fully_authenticated()' 
)); 

這裏,$ access1和$ ACCESS2將是相同的值。與IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_FULLY的行爲不同,is_remember_me函數僅在用戶通過remember-me cookie進行身份驗證時才返回true,而is_fully_authenticated僅在用戶在此會話期間實際登錄時返回true(即,是成熟的)。

使用文檔部分,我修改了我的訪問控制規則如下所示,現在的作品:

access_control: 
    - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/user/register, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/user/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } 
    - { path: ^/admin, allow_if: "has_role('ROLE_ADMIN') and is_fully_authenticated()" } 
    - { path: ^/, role: IS_AUTHENTICATED_REMEMBERED } 

不過,我仍然認爲這是一個問題,是不是預期的行爲。所以,我在正式問題跟蹤開設了一個問題:

Github的問題:#16096 - Expression engine has_role() function can't process implicit roles

0

Documentation:

添加代碼以拒絕訪問有兩種方式,以拒絕 東西訪問:

  1. 安全ACCESS_CONTROL .yml允許您保護URL模式(例如/ admin/*)。這很容易,但不太靈活;
  2. 通過security.authorization_checker服務在您的代碼中。

您正在嘗試使用第一種方式,但可以僅使用第二種方法。

你需要通過把裏面的代碼

if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) { 
    throw $this->createAccessDeniedException(); 
} 

你也可以使用SensioFrameworkExtraBundle,只是添加註釋到控制器

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; 

... 

/** 
* @Security("is_granted('IS_AUTHENTICATED_FULLY')") 
*/ 
public function showAction() 
{ 
} 
+0

德米特里,請你詳細說明爲什麼'只能靠第二個'才能做到? IS_AUTHENTICATED_FULLY是一個由symfony分配給用戶的隱式角色。因此,當你有一個訪問控制規則時,它可以工作,例如:'{path:^ /,role:IS_AUTHENTICATED_FULLY}'。那麼,爲什麼它不能用於表達? – Lashae

+0

你從哪裏得到安全配置文件支持表達式的想法?我查看了文檔並查看了解析代碼,但我沒有看到任何關於這種可能性的信息。所以這就是爲什麼我認爲只有第二種方式纔有可能 - 因爲如果您需要涉及一些高級邏輯 - 您需要使用控制器的授權限制。 –

+0

表達式支持記錄在「安全性access_control的工作方式」部分(http://symfony.com/doc/current/cookbook/security/access_control.html#securing-by-an-expression)部分。 ?」食譜文章。另外,它不是關於表達式。 '{path:^/admin,allow_if:「has_role('IS_AUTHENTICATED_FULLY')」}'也不起作用。 – Lashae