Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: К private методам можно получить доступ даже за пределами этого объекта?

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: До сегодняшнего дня, я думал, что это невозможно =)
like_you
Отправлено: 08 Июля, 2014 - 13:53:10
Post Id


Гость


Покинул форум
Сообщений всего: 82
Дата рег-ции: Июнь 2010  
Откуда: Харківська обл. с. Криштопівка


Помог: 0 раз(а)




Совсем случайно наткнулся на такой спецефект, при котором доступ к private методу можно получить даже вне объекта, который имеет этот метод. Пример
PHP:
скопировать код в буфер обмена
  1. class A{
  2.         private function priv()
  3.         {
  4.                 echo 'доступ есть';
  5.         }
  6.        
  7.         public function publ()
  8.         {
  9.                 $obj_new = new A;
  10.                 $obj_new->priv();
  11.         }
  12. }
  13.  
  14. $obj = new A;
  15. $obj->publ();

Очень интересно по какому правилу можно такое сделать. Ведь уже следующее не проходит:
PHP:
скопировать код в буфер обмена
  1. class A{
  2.         private function priv()
  3.         {
  4.                 echo 'доступ есть';
  5.         }
  6. }
  7.  
  8. class B extends A{
  9.        
  10.         public function publ()
  11.         {
  12.                 $obj_new = new B;
  13.                 $obj_new->priv();
  14.         }
  15. }
  16.  
  17. $obj = new B;
  18. $obj->publ();

Во втором примере логика запрета доступа понятна, а вот в первом... Ведь там даже не protected метод, когда можно было бы предположить, что раз объект создан на основе такого же класса, то и доступ есть...

(Отредактировано автором: 08 Июля, 2014 - 14:20:51)



-----
Створюю український хабр
 
 Top
Мелкий Супермодератор
Отправлено: 08 Июля, 2014 - 14:21:20
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Доступ проверяется относительно класса, а не объекта.
В первом случае вы из класса A вызываете метод класса А - никаких проблем, потому и вызывается. И не смотрит, что объект другой.

В частности, можно вот так:
PHP:
скопировать код в буфер обмена
  1. class A{
  2.         private function priv()
  3.         {
  4.                 echo 'доступ есть';
  5.         }
  6.  
  7.         public function publ($obj_new)
  8.         {
  9.                 $obj_new->priv();
  10.         }
  11. }
  12.  
  13. $obj = new A;
  14. $obj_new = new A;
  15. $obj->publ($obj_new);

Не помню, как к этому относятся сами разработчики PHP, но я бы не рекомендовал этим пользоваться.

like_you пишет:
при котором доступ к private методу можно получить даже вне объекта, который имеет этот метод.

Начиная с 5.4 можно штатно к любому private методу или свойству получить доступ, не имея вовсе никакого отношения к этому классу... С помощью closure::bindTo.


-----
PostgreSQL DBA
 
 Top
like_you
Отправлено: 08 Июля, 2014 - 14:32:30
Post Id


Гость


Покинул форум
Сообщений всего: 82
Дата рег-ции: Июнь 2010  
Откуда: Харківська обл. с. Криштопівка


Помог: 0 раз(а)




Мелкий пишет:
Доступ проверяется относительно класса, а не объекта.
Спасибо за ответ.
Прикольно, то есть, в самом классе можно использовать приватные методы разных объектов этого же класса.


-----
Створюю український хабр
 
 Top
and_07
Отправлено: 08 Июля, 2014 - 14:45:32
Post Id


Гость


Покинул форум
Сообщений всего: 91
Дата рег-ции: Сент. 2012  


Помог: 3 раз(а)




del

(Отредактировано автором: 08 Июля, 2014 - 14:54:38)

 
 Top
EuGen Администратор
Отправлено: 08 Июля, 2014 - 16:10:50
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Мелкий пишет:
Начиная с 5.4 можно штатно к любому private методу или свойству получить доступ, не имея вовсе никакого отношения к этому классу... С помощью closure::bindTo.

Нет, невозможно. Скажем,

PHP:
скопировать код в буфер обмена
  1. class Test
  2. {
  3.     private function privateMethod()
  4.     {
  5.         return 'caught';
  6.     }
  7. };
  8.  
  9. $c = function()
  10. {
  11.     return $this->privateMethod();
  12. };
  13.  
  14. $obj = new Test;
  15. $c   = $c->bindTo($obj);
  16. $c();

Вернёт вполне логичную ошибку несоответствия контекста (то есть, попытка доступа к приватному методу класса Test из контекста Closure)

Ну, а, скажем,

PHP:
скопировать код в буфер обмена
  1. class Test
  2. {
  3.     private function privateMethod()
  4.     {
  5.         return 'caught';
  6.     }
  7.  
  8.     public function publicMethod()
  9.     {
  10.         $c = function()
  11.         {
  12.                 return $this->privateMethod();
  13.         };
  14.         $c = $c->bindTo($this);
  15.         $c();
  16.     }
  17. };
  18.  
  19. $obj = new Test;
  20. $obj->publicMethod();

Будет работать - но это лишь частный случай уже рассмотренной выше проблемы, когда доступ проверяется на уровне текущего класса, а не конкретного экземпляра класса.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Мелкий Супермодератор
Отправлено: 08 Июля, 2014 - 16:33:44
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




EuGen пишет:
Нет, невозможно. Скажем,



-----
PostgreSQL DBA
 
 Top
EuGen Администратор
Отправлено: 08 Июля, 2014 - 16:50:01
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Мелкий пишет:
$c = $c->bindTo($obj, $obj);

Так тогда Вы получите привязку в контексте объекта (точнее, класса объекта) - это точно такая же "эмуляция" соответствующей области видимости. То есть - "извне" доступа всё равно не происходит, суть та же, что указана в примере выше, когда привязка происходит изнутри метода.

Вкратце - "извне" (из другого контекста) доступ получить не получится. bindTo с указанием области видимости как класса текущего экземпляра есть лишь встраивание кода замыкания в контекст этого класса.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Мелкий Супермодератор
Отправлено: 08 Июля, 2014 - 16:59:49
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Опять упираемся в терминологию?
Я под "извне" подразумевал отсутствие необходимости редактировать оригинальный код класса, но при этом прочитать/записать свойство объекта либо вызвать метод, не предназначенные для публичного доступа.


-----
PostgreSQL DBA
 
 Top
EuGen Администратор
Отправлено: 08 Июля, 2014 - 17:04:54
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Мелкий пишет:
Я под "извне" подразумевал отсутствие необходимости редактировать оригинальный код класса, но при этом прочитать/записать свойство объекта либо вызвать метод, не предназначенные для публичного доступа.

Такая задача имеет не единственный способ решения. Начиная уже озвученными замыканиями ("наиболее изящно") и заканчивая serialize + работа со строковым результатом + unserialize. Ничего нового в этом нет. Видимо, я действительно не корректно понял значение "извне", которое Вы имели ввиду.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
teddy
Отправлено: 08 Июля, 2014 - 17:51:58
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




Ещё обращение к приватному методу извне(тоже, что имел ввиду Мелкий) можно реализовать с помощью Reflection API

PHP:
скопировать код в буфер обмена
  1. class MyClass
  2. {
  3.     private function sayHello($name)
  4.     {
  5.         return 'Hello, '.$name;
  6.     }
  7. }
  8.  
  9. $rMethod = new ReflectionMethod('MyClass', 'sayHello');
  10. $rMethod->setAccessible(true);
  11. echo $rMethod->invoke(new MyClass, 'Mike');//Hello, Mike
 
 Top
EuGen Администратор
Отправлено: 08 Июля, 2014 - 17:55:48
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




^ If you can do something then it does not mean you should do it..
В общем - никогда не следует делать такого, не важно, замыкания это или рефлекция или что-либо другое. Это полностью ломает концепцию приватных/защищённых данных.

Это в том числе и насчёт
Мелкий пишет:
Не помню, как к этому относятся сами разработчики PHP, но я бы не рекомендовал этим пользоваться.

- то есть, совершенно правильная рекомендация так не поступать. И разработчики - да, в курсе. Но есть такие вещи, как "historically-based issues", увы.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
teddy
Отправлено: 08 Июля, 2014 - 18:02:23
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




EuGen пишет:
Это полностью ломает концепцию приватных/защищённых данных.

Соглашусь

Но и возражу:
Никто в этом топике не призывает делать подобные финты. Был задан конкретный вопрос и на него были даны конкретные ответы, не более.
 
 Top
LIME
Отправлено: 08 Июля, 2014 - 21:59:40
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




У тедди что ни пост то отражения
я б их совсем запретил
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Объектно-ориентированное программирование »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB