2017-11-16 5 views
1

REST APIを統合したSymfonyアプリケーションを開発していますが、JSONとしてユーザーエンティティを返すときにユーザーパスワードを返します。暗号化されているにもかかわらず、私はそれを避けたいです。symfony 3でJSON経由でユーザーパスワードを返さないようにする方法

マイユーザエンティティは次のとおりです。

<?php 

namespace AppBundle\Entity; 

use AppBundle\Util\Language; 
use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Security\Core\User\AdvancedUserInterface; 

/** 
* @ORM\Table(name="users") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") 
*/ 
class User implements AdvancedUserInterface, \Serializable 
{ 
    public function __construct() 
    { 
     $this->isActive = true; 
    } 


    // Functions and parameters 

    /** 
    * Set password 
    * 
    * @param string $password 
    * 
    * @return User 
    */ 
    public 
    function setPassword($password) 
    { 
     $this->password = $password; 
     return $this; 
    } 

    /** 
    * Get password 
    * 
    * 
    * @return string 
    */ 
    public function getPassword() 
    { 
     return $this->password; 
    } 

    // More functions and parameters 

    /** @see \Serializable::serialize() */ 
    public 
    function serialize() 
    { 
     return serialize(array(
      $this->id, 
      $this->username, 
      $this->password, 
      $this->isActive, 
      $this->createdAt, 
      $this->lastLogin, 
     )); 
    } 

    /** @see \Serializable::unserialize() */ 
    public 
    function unserialize($serialized) 
    { 
     list (
      $this->id, 
      $this->username, 
      $this->password, 
      $this->isActive, 
      $this->createdAt, 
      $this->lastLogin, 
      ) = unserialize($serialized); 
    } 
} 

私はAPIレスポンス

public static function createSuccessfulresponse($entity, $entityName, $responseCode, $userLocale = "en", $responseMsg = "") 
{ 
    $defResponseMsg = ($responseMsg != "" ? $responseMsg : ApiResponseCode::getMsg($responseCode, $userLocale)); 
    $responseArray = array(); 
    $responseArray['responseCode'] = $responseCode; 
    $responseArray['responseMsg'] = $defResponseMsg; 
    $responseArray['userLocale'] = $userLocale; 
    if ($entity != null) { 
     $responseArray[$entityName] = $entity; 
    } 
    return ApiResponseHelper::serializeResponse($responseArray); 
} 

レスポンス・シリアライザを構築するための静的メソッドを持っている

<?php 
namespace AppBundle\Repository; 

use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface; 
use Doctrine\ORM\EntityRepository; 

class UserRepository extends EntityRepository implements UserLoaderInterface 
{ 
    public function loadUserByUsername($username) 
    { 
     return $this->createQueryBuilder('u') 
      ->where('u.username = :username OR u.email = :email') 
      ->setParameter('username', $username) 
      ->setParameter('email', $username) 
      ->getQuery() 
      ->getOneOrNullResult(); 
    } 
} 

ユーザーリポジトリ

あなたは、私が受け取る見ることができるように

そしてuserエンティティを返すAPI呼び出しの1(以上あります)

/** 
* @Route("/api/url/{uid}") 
* @Method({"GET"}) 
*/ 
public function getByUidAction($uid) 
{ 
    $user = $this->get('security.token_storage')->getToken()->getUser(); 
    $entityManager = $this->getDoctrine()->getManager(); 
    $entity = $entityManager->getRepository('AppBundle:Workday')->findOneBy(['uid' => $uid, 'user' => $user]); 
    if($entity != null){ 
     return new Response(ApiResponseHelper::createSuccessfulresponse($entity, "workday", ApiResponseCode::SUCCESS_FETCH_WORKDAY, $user->getLocale())); 
    }else{ 
     return new Response(ApiResponseHelper::createSuccessfulresponse(null, "workday", ApiResponseCode::ERROR_EXISTS_WORKDAY, $user->getLocale())); 
    } 
} 

これは、上記の方法

{ 
    "responseCode": "successfulResponseCode", 
    "responseMsg": "Data received", 
    "userLocale": "es", 
    "workday": { 
     "id": 10, 
     ... so many data 
     "job": { 
      "id": 11, 
      .. more json data 
     }, 
     "user": { 
      "username": "amendez", 
      "password": "encrypted_password", 
      ... more data 
     }, 
     ... and more data 
    } 
} 

から1つのJSONレスポンスです暗号化されたパスワードと他の多くのデータを含むユーザーのJSONオブジェクト、私の目標は、パスワードのキーと値を返すことを避けることです。

私はそれを達成する方法を誰かが知っていますか?

+1

ユーザーエンティティでserialize関数とunserialize関数からパスワードを取り除こうとしましたか? – Chausser

+0

はい、成功せずに試しました –

+1

OPは、FOSUserBundleまたはデフォルトのファイアウォールエンティティプロバイダとの整合性を保持するために、serializeメソッドでOPを必要とします。 https://symfony.com/doc/current/security/entity_provider.html – fyrye

答えて

2

目的のゲッターが割り当てられたシリアライザグループを定義する必要があります。参照:https://symfony.com/doc/current/components/serializer.html#attributes-groups

望ましい(ベストプラクティス)方法は、望ましいグループを割り当てることです。

use Symfony\Component\Serializer\Annotation\Groups; 

class User implements AdvancedUserInterface, \Serializable 
{   
    /** 
    * @Groups({"api"}) 
    * @return string 
    */ 
    public function getUsername() 
    { 
     return $this->username; 
    } 


    //...  

    /** 
    * Get password 
    * @return string 
    */ 
    public function getPassword() 
    { 
     return $this->password; 
    } 
} 

編集ごapp/config/config.ymlでシリアライザサービス

を使いやすくするためにターンシリアライザサービスを可能にする、注釈を有効にします。

#config.yml 
framework: 
    #... 
    serializer: 
     enable_annotations: true 

今、あなたは、直接シリアライザサービスを呼び出すか、カスタムサービスでDIを使用することができます。

use Symfony\Component\Serializer\Encoder\JsonEncoder; 
use Symfony\Component\HttpFoundation\JsonResponse; 

private static function serializeResponse($responseArray) 
{ 
    $serializer = $this->container->get('serializer'); 

    return $serializer->serialize($responseArray, JsonEncoder::FORMAT, array(
     'groups' => array('api'), 
     'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS 
    )); 
} 

手動基でシリアライザコンポーネントを使用します。

use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; 
use Doctrine\Common\Annotations\AnnotationReader; 
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; 

private static function serializeResponse($responseArray) 
{ 
    $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); 

    $normalizer = new ObjectNormalizer($classMetadataFactory); 
    $encoder = new JsonEncoder(); 
    $serializer = new Serializer(array($normalizer), array($encoder)); 

    return $serializer->serialize($responseArray, JsonEncoder::FORMAT, array('groups' => array('api'))); 
} 

別の方法としては、無視された属性の一部としてそれを設定することができるはずです。参照してください:https://symfony.com/doc/current/components/serializer.html#ignoring-attributes

+0

ありがとうございます@fyryeそれは同じだが別の方法であるため、最初のアプローチもうまくいくと思います。私はあなたがそれを行うための推奨された方法だと言っているので、私はそれを試してみましょう、私はあなたに知らせる任意の旗を見つける場合。私は本当にあなたの助けに感謝:) –

+0

問題はありません。 Symfonyが推奨する理由は、利用可能なグループコンテキストの宣言が中心的な場所にあるということです。したがって、保守、トラブルシューティング、および検証がずっと簡単です。手動で無視されるように、コントローラやサービス全体に散在するのとは対照的です。別のAPIをシリアル化して呼び出すと、そのパスワードを無視する必要があることを忘れているとします。 – fyrye

+0

ええ、私は可能な限り維持しやすくすることを好むので、他のアプローチに変更すると思います。助けと素敵な情報ありがとうございました –

関連する問題