如何使用 FOS User Bundle 和 Symfony 4 使用 JMS 序列化程序从用户实体中排除密码字段?

How to exclude password field from the user entity with JMS serializer using FOS User Bundle and Symfony 4?

我已经使用 FOSUserBundle 和 JWT(使用 LexikJWTAuthenticationBundle)实现了简单的 API 登录功能。一切正常,我可以登录并获得 jwt 令牌。但是当我创建 API 端点以获取用户详细信息时,密码字段也会在响应中发送。

我的控制器获取用户详细信息的方法如下所示:

/**
 * @Route("/get/{id}", name="api_auth_get_user_by_id",  methods={"GET"})
 *
 * @param Request              $request
 * @param UserManagerInterface $userManager
 *
 * @return JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
 */
public function getById(SystemUser $user)
{
    return $this->handleView($this->view($user));
}

我的用户实体如下所示:

<?php

namespace App\Entity\Api\Auth;

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class SystemUser extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();
        // your own logic
    }
}

正如您所见,我的 SystemUser 实体是从 FOSUserBundle 中找到的 BaseUser 实体扩展而来的。

这是当我从 API:

获取用户详细信息时响应 JSON 的样子
{
    "id": 1,
    "username": "test",
    "username_canonical": "test",
    "email": "test.user@super.com",
    "email_canonical": "test.user@super.com",
    "enabled": true,
    "password": "y$DnyFxYyJXQe3Z7chsJYwe.LUsuOWPqBtFm5.O0vwldX5AoMGld9ca",
    "last_login": "2019-08-27T06:19:43-04:00",
    "groups": [],
    "roles": []
}

那么如何从响应中排除密码 属性。我正在使用最新的 Symfony 4.3。我知道在 Symfony 的早期版本中,您可以为捆绑包中的每个实体创建一个 jms 序列化程序配置,但在 Symfony 4 中发生了如此多的变化,现在不需要使用捆绑包,而且我没有为这个简单的应用程序使用捆绑包。

从扩展 FOS 用户包用户实体的实体中排除密码 属性 的正确方法是配置 packages/jms_serializer.yaml 配置,如下所示:

jms_serializer:
    metadata:
        auto_detection: true
        directories:
            FOSUB:
                namespace_prefix: 'FOS\UserBundle'
                path: '%kernel.root_dir%/serializer' 

另请注意,namespace_prefix 必须使用单个 \,因为这将不起作用:

namespace_prefix: 'FOS\UserBundle'

第二步是为 FOS 用户实体创建 JMS 序列化文件,具体如下:

FOS\UserBundle\Model\User:
    exclusion_policy: ALL
    properties:
        id:
            expose: true
        username:
            expose: true
        password:
            expose: false
        email:
            expose: true
        last_login:
            expose: true
        enabled:
            expose: true

可以保存在src/serializer/Model.User.yml

让我感到困惑的一件事是您无法在子 class.

的配置文件中为父 class 配置序列化属性

例如,如果您要使用另一个实体 SystemUser 扩展 FOS\UserBundle\Model\User 实体,并在 src/serialization/Entity.SystemUser.yml 中为该新实体创建序列化配置文件。从该 Entity.SystemUser.yml 文件中,您不能排除或配置属于
的任何属性 FOS\UserBundle\Model\User 实体。对于每个父 class 实体,您必须创建自己的序列化配置文件。

也不要忘记在更改序列化配置后清除缓存。