如何实现基于角色的 REST API

How to implement Role-based REST API

我在我的项目中有两个不同的角色:ROLE_USERROLE_ADMIN
我想通过 REST API's url '/users' 获取所有用户的列表,但有些字段(例如 email)只能看到那些通过 ROLE_ADMIN.
进行身份验证的人 所以,我通常有 2 个问题:

1) 我应该根据ROLE
决定在哪个抽象级别(在MVC模式中)可以返回哪些信息 2) 在 Symfony 中实现这种基于角色的 REST API 的最佳方式是什么?


谢谢

由于API取决于发出请求的用户,每个请求都必须携带有关当前用户的信息。通常所有与授权相关的任务都在控制器内处理。因此,第一个问题的答案是,您应该在控制器中处理角色,并根据角色,从存储库 returned 的数据中过滤掉字段。例如,

//users is the array of user objects returned by your repository

data = [];

if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
  foreach($users as $user){
  // Add ROLE_ADMIN specific data
        data[][] = array(
            'name' => $user->getName(),
            'email' => $user->getEmail(),
        );
  }     
}


if ($this->get('security.context')->isGranted('ROLE_USER')) {
   foreach($users as $user){
    // Add ROLE_USER specific data
    data[][] = array(
        'name' => $user->getName(),
        'address' => $user->getAddress(),
               );
   } 

  }

然后,JSON 对数据数组进行编码,return 作为响应。要减少查询次数,您可以在 User class.

中添加一个 __toArray 方法

如果您正在使用 JMSSerializer,您可以使用群组来决定可以看到或不可以看到的内容。然后在你的控制器中,或者任何地方,你可以根据角色设置组。

例如映射(在 YAML 中)..

Fully\Qualified\Class\Name:
    exclusion_policy: ALL
    properties:
        id:
            groups: [user]
        userAndAdmin:
            groups: [user]
        adminOnly:
            groups: [admin]

然后在您的控制器中将组设置为...

public function getUsersAction(Request $request)
{
    $users = $this->getRepository()->findAll();
    $serializer = $this->get('jms_serializer.serializer');

    $json = $serializer->serialize(
        $users,
        'json',
        SerializationContext::create()->setGroups($this->generateGroups())
    );

    return new Response($json);

    // If you are using FOSRestBundle, which I would recommend, then you would just need to do...
    $view = $this
        ->view($this->getRepository()->findAll();)
        ->setExclusionGroups($this->generateGroups())
    ;

    return $this->handleView($view);
}

private function generateGroups()
{
    $securityContext = $this->get('security.context');
    $groups = array();

    if ($securityContext->isGranted('ROLE_USER')) {
        $groups[] = 'user';
    }

    if ($securityContext->isGranted('ROLE_ADMIN')) {
        $groups[] = 'admin';
    }

    return $groups;
}

虽然整个 "generateGroups" 和设置组最好放在客户视图处理程序或响应生成器中。

假设您的层次结构有 ROLE_ADMIN 作为 ROLE_USER 的父级,您将得到以下结果。

ROLE_USER

{
    "users": [
        {
            "id": 1,
            "userAndAdmin": "val"
        }
    ]
} 

ROLE_ADMIN

{
    "users": [
        {
            "id": 1,
            "userAndAdmin": "val",
            "adminOnly": "val"
        }
    ]
}