Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Frameworki _ [Symfony]Tworzenie własnej funkcji w @Security

Napisany przez: emillo91 20.09.2018, 13:05:50

Witam. Chciałem się zapytać czy jest możliwe dodanie nowej funkcji do klasy Security. Chodzi mi o utworzenie funkcji podobnej do is_granted() z tym że ma ona sprawdzać czy ranga użytkownika o danym id ma dostęp do danej metody kontrolera. Znalazłem artykuły jak tworzyć własne adnotacje lecz nie znalazłem nic na temat mojego problemu. Oczywiście mógłbym utworzyć metodę w kontrolerze, która sprawdzałaby id rangi użytkownika lecz zależy mi na estetyce i chciałbym aby to wszystko znalazło się w PHP DOC.

Napisany przez: Damonsson 25.09.2018, 00:19:45

Jeśli zależy Ci na estetyce to zapomnij, że coś takiego jak adnotacje (jeśli wpływają na działanie aplikacji, konfigurują cokolwiek itp.) w ogóle istnieje.

Napisany przez: kleus 25.09.2018, 09:56:18

Oczywiscie... Musisz napisac class ktora dziedziczy po Security. W tej klasie dodajesz swoja method do sprawdzenia czy user ma dostep do ackji controllera.
Zostaje nadpisanie config symfony zeby Container wywowal twoja classe zamiast default... no i phpunit ;D

Napisany przez: athabus 25.09.2018, 16:37:00

Nie wiem dokładnie co chcesz osiągnąć, ale może uda się to zrobić za pomocą https://symfony.com/doc/current/security/voters.html ?

Napisany przez: emillo91 27.09.2018, 10:03:14

Dzięki za pomoc. Athabus zrobilem to przy pomocy Voterów i raczej nie będzie potrzebne inne rozwiązanie. Jest mi to potrzebne do ustalania dostępu do danej akcji dla id grupy użytkownika z bazy danych ( administrator ma dostęp do wszystkich akcji, moderator do wybranych itd.) i administrowania dostępem poprzez bazę danych. Dodatkowo udało mi się stworzyć dodawanie indywidualnych uprawnień do akcji dla danego użytkownika. Jutro postaram się wrzucić moje rozwiązanie.

Poniżej udostępniam voter sprawdzający uprawnienia do akcji dla rangi użytkownika oraz uprawnienia do akcji dla id użytkownika. Voter operuje na dwóch tabelach. Jeżeli nie zostanie znalezione id rangi użytkownika w jednej tabeli to szuka id uprawnionego użytkownika w drugiej tabeli.

  1.  
  2. <?php
  3. /**
  4.  * Created by PhpStorm.
  5.  * User: E
  6.  * Date: 23.09.2018
  7.  * Time: 19:54
  8.  */
  9.  
  10. namespace AppBundle\Security;
  11.  
  12.  
  13. use AppBundle\Entity\Pageroutes;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Symfony\Component\HttpFoundation\RequestStack;
  16. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  17. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  18.  
  19. class RankroutesVoter extends Voter
  20. {
  21.  
  22. const EDIT = 'edit';
  23.  
  24. private $entityManager;
  25. private $request;
  26.  
  27. public function __construct(EntityManagerInterface $entityManager, RequestStack $requestStack)
  28. {
  29. $this->entityManager = $entityManager;
  30. $this->request = $requestStack->getCurrentRequest()->attributes->get('_route');
  31. }
  32.  
  33. /**
  34.   * Determines if the attribute and subject are supported by this voter.
  35.   *
  36.   * @param string $attribute An attribute
  37.   * @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
  38.   *
  39.   * @return bool True if the attribute and subject are supported, false otherwise
  40.   */
  41. protected function supports($attribute, $subject)
  42. {
  43. if (!http://www.php.net/in_array($attribute, http://www.php.net/array(self::EDIT))) {
  44. return false;
  45. }
  46.  
  47. return true;
  48. }
  49.  
  50. /**
  51.   * Perform a single access check operation on a given attribute, subject and token.
  52.   * It is safe to assume that $attribute and $subject already passed the "supports()" method check.
  53.   *
  54.   * @param string $attribute
  55.   * @param mixed $subject
  56.   * @param TokenInterface $token
  57.   *
  58.   * @return bool
  59.   */
  60. protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
  61. {
  62. //get current user
  63. $user = $token->getUser();
  64.  
  65. //get repository
  66. $pageroutes = $this->entityManager->getRepository(Pageroutes::class);
  67.  
  68. //check that logged user rank is granted to actual request route
  69. $findroute = $pageroutes->findPageroutesRankRoute($user, $this->request);
  70.  
  71. //check that logged user id is granted to actual request route
  72. $finduserroute = $pageroutes->findUserranksRankRoute($user, $this->request);
  73.  
  74. $getPageroutesData = null;
  75.  
  76.  
  77. foreach($findroute as $userRankId)
  78. {
  79.  
  80. foreach($userRankId->getRankid() as $fielddata)
  81. {
  82. $getPageroutesData = $fielddata;
  83. }
  84. }
  85.  
  86. foreach($finduserroute as $userRankId)
  87. {
  88. $getPageroutesData = $userRankId;
  89.  
  90. }
  91. switch ($attribute) {
  92. case self::EDIT:
  93. // if the user rank is granted to pageroute allow them to edit page
  94. if ($user->getRankid() === (object)$getPageroutesData) {
  95. return true;
  96. }
  97. // if the user id is granted to pageroute allow them to edit page
  98. if ($user === (object)$getPageroutesData) {
  99. return true;
  100. }
  101. return false;
  102. break;
  103. }
  104.  
  105. return false;
  106. }
  107.  
  108. }


poniżej fragmenty repozytorium, odpowiedzialne za wyszukiwanie id rangi lub id użytkownika, dla którego mają zostać przyznane uprawnienia do akcji:

PageroutesRepository.php:
  1.  
  2. /**
  3.   * @param Users $users
  4.   * @param $string
  5.   * @return array
  6.   */
  7. public function findPageroutesRankRoute(Users $users, $string)
  8. {
  9. return $this->getEntityManager()
  10. ->createQuery(
  11. "SELECT p
  12. FROM AppBundle:Pageroutes p
  13. LEft Join p.rankid a
  14. WHERE a.rankid = :rankid
  15. And p.routename = :routename"
  16. )
  17. ->setParameter("rankid", $users->getRankid())
  18. ->setParameter("routename", $string)
  19. ->getResult();
  20. }
  21.  
  22. /**
  23.   * @param Users $users
  24.   * @param $string
  25.   * @return array
  26.   */
  27. public function findUserranksRankRoute(Users $users, $string)
  28. {
  29. return $this->getEntityManager()
  30. ->createQuery(
  31. "SELECT u
  32. FROM AppBundle:Users u
  33. LEft Join u.routeid r
  34. WHERE u.userid = :userid
  35. And r.routename = :routename"
  36. )
  37. ->setParameter("userid", $users->getUserid())
  38. ->setParameter("routename", $string)
  39. ->getResult();
  40. }
  41.  


Wszytko działa tylko, że problem pojawi się w momencie, gdy będę chciał zmienić nazwę stałej wywołującej określone działanie votera. Wtedy będę musiał ją zmienić we wszystkich akcjach, w których doczepiłem adnotację @security. Oczywiście nie będzie problemem wyedytowanie tych nazw ale jak będę miał 200 lub więcej akcji to zajmie to trochę czasu dry.gif

Napisany przez: rad11 30.09.2018, 08:35:03

Nie koniecznie , mozesz stworzyc mape nazw ktora bedzie konfigurowalna i wtedy dasz np
[
edit => [
edit1,edit2
]
]
Wtedy w klasie votera jestes w stanie to ogarnac i nie musisz wszedzie zmieniac

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)