2013-01-07 22 views
6

Tôi hơi bối rối bởi cách danh sách điều khiển truy cập được thực hiện trong Symfony2.Làm thế nào để thực hiện vai trò/tài nguyên ACL trong Symfony2

Trong Zend Framework (phiên bản 1 & 2), một danh sách các nguồn và một danh sách các vai trò được định nghĩa và vai trò của từng được gán một tập hợp con của các nguồn tài nguyên nó cho phép truy cập. Do đó, các tài nguyên và vai trò là vốn từ vựng chính của việc triển khai ACL, không phải là trường hợp trong Symfony2, nơi chỉ có các quy tắc vai trò.

Trong cơ sở dữ liệu ứng dụng cũ, tôi có bảng xác định danh sách vai trò, danh sách tài nguyên và danh sách tài nguyên được phép cho từng vai trò (mối quan hệ nhiều-nhiều). Mỗi người dùng được chỉ định vai trò (quản trị viên, quản trị viên cấp cao, người chỉnh sửa và những người khác).

Tôi cần sử dụng cơ sở dữ liệu này trong ứng dụng Symfony2. nguồn lực của tôi trông như thế này: ARTICLE_EDIT, ARTICLE_WRITE, COMMENT_EDIT vv

User thực thể của tôi trong Symfony cài đặt giao diện Symfony\Component\Security\Core\User\UserInterface và do đó có một phương pháp getRoles).

Tôi dự định sử dụng phương pháp này để xác định tài nguyên được phép, có nghĩa là tôi sử dụng vai trò làm tài nguyên (nghĩa là tài nguyên được gọi là Zend Framework được gọi là vai trò ở đây).

Bạn có xác nhận rằng tôi nên sử dụng phương pháp này không?

Điều này có nghĩa là tôi không quan tâm nữa về vai trò (quản trị viên, người biên tập, ...) của từng người dùng, mà chỉ về tài nguyên của nó.

Sau đó tôi sẽ sử dụng $this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE') trong bộ điều khiển của mình.

Đây có phải là cách phù hợp để làm điều đó và nó sẽ không phải là cách phá cách để sử dụng các vai trò trong Symfony?

Trả lời

2

Để trả lời câu hỏi này năm sau, nó đã được khá dễ dàng để giải quyết.

Giải pháp là kết hợp các khái niệm về vai trò và tài nguyên.

Giả sử một bảng role, một bảng resource và và role_resource nhiều mối quan hệ được xác định.

Người dùng được lưu trữ trong bảng user.

Dưới đây là các thực thể thuyết tương ứng:

User:

use Symfony\Component\Security\Core\User\UserInterface; 

class User implements UserInterface 
{ 
    /** 
    * @Id @Column(type="integer") 
    * @GeneratedValue 
    */ 
    private $id; 

    /** 
    * @ManyToOne(targetEntity="Role") 
    * @JoinColumn(name="role_id", referencedColumnName="id") 
    **/ 
    private $role; 

    // ... 
} 

Vai trò:

class Role 
{ 
    /** 
    * @Id @Column(type="integer") 
    * @GeneratedValue 
    */ 
    private $id; 

    /** @Column(type="string") */ 
    private $name; 

    /** 
    * @ManyToMany(targetEntity="Resource") 
    * @JoinTable(name="role_resource", 
    *  joinColumns={@JoinColumn(name="role_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@JoinColumn(name="resource_id", referencedColumnName="id")} 
    *  ) 
    **/ 
    private $resources; 

    // ... 
} 

Resource:

class Resource 
{ 
    /** 
    * @Id @Column(type="integer") 
    * @GeneratedValue 
    */ 
    private $id; 

    /** @Column(type="string") */ 
    private $name; 

    // ... 
} 

Vì vậy, bây giờ giải pháp là để thực hiện getRoles của UserInterface theo cách này:

use Symfony\Component\Security\Core\User\UserInterface; 
use Symfony\Component\Security\Core\Role\Role; 

class User implements UserInterface 
{ 
    // ... 

    /** 
    * @var Role[] 
    **/ 
    private $roles; 

    /** 
    * {@inheritDoc} 
    */ 
    public function getRoles() 
    { 
     if (isset($this->roles)) { 
      return $this->roles; 
     } 

     $this->roles = array(); 

     $userRole = $this->getRole(); 

     $resources = $userRole->getResources(); 

     foreach ($resources as $resource) { 
      $this->roles[] = new Role('ROLE_' . $resource); 
     } 

     return $this->roles; 
    } 

} 

Bằng cách này, các nguồn lực do người sử dụng hiện tại có thể được kiểm tra theo cách này (xem xét có một nguồn tài nguyên có tên là ARTICLE_WRITE):

$this->get('security.context')->isGranted('ROLE_ARTICLE_WRITE')