我目前正在使用FOSRESTBundle和JMSSeriize来制作一个RESTFullAPI(当然)。
我的项目是面向客户和管理员的外联网。
以这种方式,我必须禁用一些字段被客户查看,仅对管理员可见。
我首先为实体进行了以下序列化程序配置:
AppBundle\Entity\IncidentComment:
exclusion_policy: ALL
properties:
id:
expose: true
groups: [list, details]
author:
expose: true
groups: [list, details]
addedAt:
expose: true
groups: [list, details]
content:
expose: true
groups: [details]
customerVisible:
expose: true
groups: [list_admin, details_admin]
如您所见,CusterViable
组有_admin
后缀。此字段应仅为管理员显示。
我想动态添加带有\u admin
后缀的组,以便在视图上设置组,前提是用户有一个角色\u admin角色或其他条件,而不在每个rest控制器的每个操作上写入它。
我正在考虑创建一个带有安全上下文参数的自定义视图处理程序来添加组,但我不知道这是否是正确的方法。
你认为是好方法吗?你对此有什么建议吗?
顺便说一句,如果一些开发人员有同样的问题,我会很高兴在这里告诉您他是如何解决的!:)
谢谢
除了@Vladislav Kopaygorodsky的响应之外,这些添加允许它工作,即使您在控制器中的函数中省略了@View
注释:
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use AppBundle\Security\User;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use FOS\RestBundle\Controller\Annotations\View as ViewAnnotation;
/**
* Listener to automatically adjust serializer groups based on user roles.
*
* If a user is granted the USER_XYZ role, then this function will add the
* serializer group "has_role_xyz" before the automatic serialization takes
* place on the data returned from a controller.
*/
class PermissionResponseListener
{
private $authorizationChecker;
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
public function onKernelView(GetResponseForControllerResultEvent $event)
{
$attr = $event->getRequest()->attributes;
if (null === $viewAttribute = $attr->get('_template')) {
// No @Rest\View annotation, create a blank one.
$viewAttribute = new ViewAnnotation(array());
$viewAttribute->setPopulateDefaultVars(false);
$attr->set('_template', $viewAttribute);
}
$groups = $viewAttribute->getSerializerGroups();
// Always include this group, since the default value set in
// config.yml is no longer used.
$groups[] = 'Default';
foreach (User::getPossibleRoles() as $role) {
if ($this->authorizationChecker->isGranted($role)) {
$groups[] = 'has_' . strtolower($role); // ROLE_USER => has_role_user
}
}
$viewAttribute->setSerializerGroups($groups);
}
}
User类有一个函数,它只列出所有可用的角色:
public static function getPossibleRoles()
{
return [
'ROLE_ADMIN', // system administrators
'ROLE_OFFICE', // data entry staff
'ROLE_USER', // anyone logged in
];
}
和服务。yml:
# Set serializer groups based on user roles
AppBundle\EventListener\PermissionResponseListener:
public: false
tags:
- { name: kernel.event_listener, event: kernel.view, method: onKernelView, priority: 101 }
在实体中,您现在可以使用注释,如:
class ExampleEntity {
/**
* @Serializer\Groups({"has_role_admin"})
*/
protected $adminOnlyValue;
如果您想使用侦听器执行此操作,可以创建自己的viewerresponselistener
并将其订阅到事件内核。查看
。您的侦听器必须在FOSRest listener之后被激发,因此,您必须设置101优先级。
app.event.listener.extended_view_response:
class: AppBundle\EventListener\ExtendedViewResponseListener
arguments: ["@security.authorization_checker"]
tags:
- { name: kernel.event_listener, event: kernel.view, method: onKernelView, priority: 101 }
ExtendedViewResponseListener。php
public function onKernelView(GetResponseForControllerResultEvent $event)
{
if (null !== $viewAttribute = $event->getRequest()->attributes->get('_template')) {
$groups = [];
foreach(User::getPossibleRoles() as $role) {
if ($this->authorizationChecker->isGranted($role)) {
$groups[] = strtolower(str_replace('ROLE_', '', $role)); // ROLE_USER => user group
}
}
$viewAttribute->setSerializerGroups($groups);
}
}
并且,请不要忘记在控制器中启用_template
属性,我的意思是在控制器注释中启用@\FOS\RestBundle\Controller\Annotions\View()
。如果你想弄清楚它是如何工作的-请检查FosRestBundle中的ViewResseListener.php。
第二种方法-自定义序列化程序tokenstorageaware\u序列化程序
我刚刚找到了一种在运行时添加SerializerGroup的简单方法:
private function determineRolebasedSerializerGroup($role, $groupToAdd, Request $request) {
if (!$this->get('security.context')->isGranted($role))
return;
$groups = $request->attributes->get('_view')->getSerializerGroups();
$groups[] = $groupToAdd;
$x = $request->attributes->get('_view')->setSerializerGroups($groups);
}
我已将此方法添加到我的控制器中。我现在可以这样称呼它:
/**
* @REST\View(serializerGroups={"company"})
*/
public function getCompanyAction(Company $company, Request $request) {
$this->determineRolebasedSerializerGroup('ROLE_ADMIN', 'company-admin', $request);
return $company;
}
如果当前用户具有角色"ROLE_ADMIN",则将组"compent-admin"添加到序列化程序组。这对我很有用。
提前感谢您的帮助!我正在学习一个教程,当我尝试启动我在karaf中安装的捆绑包时,它不会启动...日志是: 20:12:18.713 错误 [Karaf 本地控制台用户 karaf] 执行命令 org.apache.karaf.shell.support.MultiException 时捕获异常:在捆绑包上执行命令时出错:启动捆绑包 157 时出错:无法解析 db-examplejpa [157]
我正在使用和作为模块绑定器编写一个web应用程序。到目前为止,我的代码非常轻,整个文件夹的大小是25kb。 然而,我的是从创建的,其大小为2.2MB。在使用标志运行优化后,它将捆绑包减少到700kb,这仍然非常大。 我已经查看了文件,它的大小是130kb。 有没有可能webpack产生了这么大的文件,或者我做错了什么? webpack.config.js 编辑 package.json:
我有与SQLite数据库工作的应用程序。我把它打包成一个包,我可以看到服务组合上的服务。当我发送请求到发布或获取服务我收到这个错误: JAVAlang.ClassNotFoundException:org。sqlite。未找到JDBC 我在servicemix上安装了SQLite JDBC驱动程序,但仍然出错。 这是我的POM: 我试图把这个组织。旱生。sqlite jdbc仅作为导出包和导入包,
问题内容: 编辑:Symfony最佳做法回答了我的大部分问题。 关于我的Symfony2应用程序,我有几个问题。 它将有一个前端和一个后端,并且它们将使用一些通用代码(例如日期显示器,分页器,一些经常使用的模板等)。 因此,我创建了一个FrontendBundle和一个BackendBundle,它们分别包含各自的布局。第一个问题:为前端和后端创建捆绑包(这是甚至没有控制器的“通用”捆绑包)的优良
我使用EclipseIndigo使用OSGiJava框架开发了一些包。有一个主捆绑包,它依赖于其他捆绑包,并且具有要运行的主程序。如果我尝试在Eclipse中运行所有捆绑包,一切都正常工作,但是如果我将每个捆绑包保存为一个JAR,并在命令行中启动OSGi框架,当我尝试启动主捆绑包时,会出现异常<code>NoClassDefFoundError。找不到的类是依赖项。包的其余部分处于活动状态,主包刚
无法解析 karaf 中的捆绑包。此处的日志: 在这个模块中,使用openjpa创建数据库。