我的项目中有两个不同的角色:ROLE_USER
和ROLE_ADMIN
我希望通过 REST API的网址'/users'
获取所有用户的列表,但某些字段(例如email
)只能看到使用{{1}进行身份验证的人}。
所以,我一般有两个问题:
1)我应该根据ROLE_ADMIN
决定在哪个抽象级别(MVC
模式)中返回哪些信息
2)哪种是在Symfony中实现这种基于角色的REST API的最佳方式?
由于
答案 0 :(得分:3)
如果您使用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"
}
]
}
答案 1 :(得分:0)
由于API依赖于发出请求的用户,因此每个请求都必须携带有关当前用户的信息。通常,所有与授权相关的任务都在控制器内处理。因此,回答第一个问题是您应该在控制器中处理角色并根据角色,您应该从存储库返回的数据中过滤掉字段。例如,
//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编码数据数组并作为响应返回。要减少查询数,可以在User类中添加__toArray方法。