Страницы

Поиск по вопросам

Показаны сообщения с ярлыком symfony. Показать все сообщения
Показаны сообщения с ярлыком symfony. Показать все сообщения

воскресенье, 8 марта 2020 г.

Медленный ли Symfony?

#php #производительность #symfony #phalcon


В данный момент, решил попробовать Symfony 3 на PHP 7, и задаюсь вопросом производительности.

Есть задача написания REST API, решил попробовать Symfony 3, написал тестовое API
и попробовал выполнить тест Apache AB (ab -t 10 -c 10) на несуществующий метод, скорость
обработки 2062 запроса за 10 секунд или 206 запросов в секунду.

Делаю тоже самое на Phalcon, скорость 23297 запросов за 10 секунд или 2329.69 запросов
в секунду. Если запускать один запрос, то скорость одинаковая, примерно 90 мс.

В чем прикол? Может я что-то делаю неправильно и где-то нужно настроить что-то, чтобы
на несуществующий запрос была более высокая скорость или это нормальная скорость? Я
понимаю, что Symfony имеет высокую абстракцию, за нее нужно платить, и поэтому производительность
меньше, но тут просто нужно просто вывести 404 ошибку и такой сумасшедший отрыв.

Отрыв Phalcon становится меньше, если взять и добавить операцию поиска в базу и маппинга,
через модель встроенную в фреймворк. Phalcon правда всеравно быстрее, 1600 запросов
против 900 запросов Symfony за 10 секунд.

Конфигурация: PHP 7, Debian, opcache on, Symfony3, Phalcon 3, Кеш Symfony включен,
режим Production.

Подключенные бандлы в Symfony:

new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
new FOS\RestBundle\FOSRestBundle(),
new JMS\SerializerBundle\JMSSerializerBundle(),
new Nelmio\CorsBundle\NelmioCorsBundle()


app.php:

use Symfony\Component\HttpFoundation\Request;

/**
 * @var Composer\Autoload\ClassLoader
 */
$loader = require __DIR__.'/../app/autoload.php';
include_once __DIR__.'/../var/bootstrap.php.cache';

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$kernel = new AppCache($kernel);

// When using the HttpCache, you need to call the method in your front controller
instead of relying on the configuration parameter
Request::enableHttpMethodParameterOverride();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);




Ладно, делаем замеры потребляемых ресурсов при выполнении запроса в базу данных на
поиск и маппинг:

Выполняем замер Symfony и существующей конфигурации PHP-FPM при работе Apache AB
(ab -t 10 -c 10):

20383 www-data 20 0 380884 26040 18020 R **58,3** 0,3 0:10.35 php-fpm7.0
21394 www-data 20 0 380884 26040 18020 R **57,3** 0,3 0:03.62 php-fpm7.0
21498 www-data 20 0 380884 25908 17900 R **57,3** 0,3 0:02.77 php-fpm7.0
19479 www-data 20 0 380884 25020 18020 D **55,7** 0,3 0:15.08 php-fpm7.0
20481 www-data 20 0 380884 26044 18020 R **52,0** 0,3 0:09.30 php-fpm7.0


Окей, в среднем FPM жрет 52 процента ядра на каждый процесс, делаем замер Phalcon:

24110 www-data 20 0 379016 17876 12848 S **13,6** 0,2 0:03.57 php-fpm7.0
25593 www-data 20 0 378884 17776 12848 R **13,3** 0,2 0:02.30 php-fpm7.0
27023 www-data 20 0 378884 17608 12788 S **13,3** 0,2 0:01.08 php-fpm7.0
25445 www-data 20 0 378884 17780 12848 S **13,0** 0,2 0:02.48 php-fpm7.0
27177 www-data 20 0 378884 17600 12788 R **13,0** 0,2 0:00.91 php-fpm7.0


Phalcon не грузит систему, при одинаковых действиях, загрузка на каждый процесс 13
процентов. 

Я могу предположить, что возможно скорость меньше и нагрузка выше из-за того, что
Symfony дергает кеш с диска каждый раз, а Phalcon по умолчанию все пишет в память.
Если это так, то как перенести весь кеш в память, чтобы исключить нагрузку на диск? 

Кто разбирается в Symfony, скажите, как сделать его быстрее и возможно ли это? В
чем ошибка?
    


Ответы

Ответ 1



фалькон быстрый потому, что написан как расширение для PHP на С Да, симфони очень медленный, вовсе не по тому, что "Symfony дергает кеш с диска каждый раз, а Phalcon по умолчанию все пишет в память.", а потому, что представляет собой достаточно толстую прослойку уймы абстракций. Нет, невозможно. Они предназначены для разных задач. Удобство клепать мелкие сайты с модным MVC на Симфони vs условно-хардкорная производительность чистых сей для фалькона. и нет, у вас не получится как-то супер-быстро разрешать нагрузку на на существующий урл, если все урлы обрабатывает симфони, если урл дошел от веб-сервера до симфони, она его еще как обработает. Придется решать проблему несуществующих урлов как-то по-другому (на стороне веб-сервера) Сделать симфоню быстрее можно, наверное, настроив правильное кэширование (opcache), но тем не менее, с фальконом она не сможет соревноваться по скорости. Т.е. даже симфоневый раутинг (я про 404) будет медленней фальконовского. Кроме того, использование Апача в качестве сервера для хайлоада не oche рекомендуется (возможно, он, конечно, вырос за последние годы) P.S. Как я уже говорил, 36 тысяч вызовов функции substr на один http запрос в Симфони... ну.. окей.

Ответ 2



Привет из 2018, Symfony 4 теперь мега крутой, мощный и при этом быстрый микрофреймворк со своим Flex плагином для Composer-а и конкурентов 0.

пятница, 24 января 2020 г.

Проблемы при настройке symfony 2.7 и 3.0 (проблема одна и та же)

#php #framework #symfony2 #symfony #symfony3


Проблемы при настройке symfony 2.7 и 3.0 (проблема одна и та же)


  Major problems have been detected and must be fixed before continuing:
  Change the permissions of either "app/cache/" or "var/cache/"
  directory so that the web server can write into it. Change the
  permissions of either "app/logs/" or "var/logs/" directory so that the
  web server can write into it.


Стандартные решения, естественно, попробовал из документации Symfony, глава Checking
Symfony Application Configuration and Setup.

Setting up Permissions:

Yuri@localhost /v/w/symfony.loc> sudo rm -rf var/cache/*
Yuri@localhost /v/w/symfony.loc> sudo rm -rf var/logs/*
Yuri@localhost /v/w/symfony.loc> sudo setfacl -R -m u:apache:rwX -m u:Yuri:rwX var/cache
var/logs
Yuri@localhost /v/w/symfony.loc> sudo setfacl -dR -m u:apache:rwX -m u:Yuri:rwX var/cache
var/logs
Yuri@localhost /v/w/symfony.loc> sudo service httpd restart
Redirecting to /bin/systemctl restart  httpd.service


Группа у web-server точно apache. Пруф

Yuri@localhost /v/w/symfony.loc> 
ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v
root | head -1 | cut -d\  -f1
apache
Yuri@localhost /v/w/symfony.loc>


Так же использовал крайние решение из главы Setting up Permissions:
подставил в начало файлов: (bin/console, web/app.php и web/app_dev.php) -> umask(0000)
в начало;

Yuri@localhost /v/w/symfony.loc> sudo service httpd restart
Redirecting to /bin/systemctl restart  httpd.service
Yuri@localhost /v/w/symfony.loc> service httpd status
Redirecting to /bin/systemctl status  httpd.service
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset:
disabled)
   Active: active (running) since Чт 2015-12-24 23:17:13 MSK; 11min ago
 Main PID: 9196 (httpd)
   Status: "Total requests: 8; Idle/Busy workers 100/0;Requests/sec: 0.0121; Bytes
served/sec:  51 B/sec"
   CGroup: /system.slice/httpd.service
           ├─9196 /usr/sbin/httpd -DFOREGROUND
           ├─9197 /usr/sbin/httpd -DFOREGROUND
           ├─9198 /usr/sbin/httpd -DFOREGROUND
           ├─9199 /usr/sbin/httpd -DFOREGROUND
           ├─9201 /usr/sbin/httpd -DFOREGROUND
           ├─9205 /usr/sbin/httpd -DFOREGROUND
           ├─9207 /usr/sbin/httpd -DFOREGROUND
           └─9354 /usr/sbin/httpd -DFOREGROUND

дек 24 23:17:13 localhost.localdomain systemd[1]: Starting The Apache HTTP...
дек 24 23:17:13 localhost.localdomain httpd[9196]: AH00548: NameVirtualHos...
дек 24 23:17:13 localhost.localdomain systemd[1]: Started The Apache HTTP ...
Hint: Some lines were ellipsized, use -l to show in full.
Yuri@localhost /v/w/symfony.loc> 


Nginx и php-fpm точно не включен 

Yuri@localhost /v/w/symfony.loc> sudo service php-fpm status
[sudo] пароль для Yuri: 
Redirecting to /bin/systemctl status  php-fpm.service
● php-fpm.service - The PHP FastCGI Process Manager
   Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset:
disabled)
   Active: inactive (dead)
Yuri@localhost /v/w/symfony.loc> sudo service nginx status
Redirecting to /bin/systemctl status  nginx.service
● nginx.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)
Yuri@localhost /v/w/symfony.loc>


На просторах Ru&En-нета не нашел больше решений:(
Повторюсь, проблема на symfony 2.7 и 3.0 идентична. Пробовал на fedora 22 php5.6.15
и php7. Пробовал уже различные комбинации владельцев apache:Yuri, в том числе и на
создание новых файлов тоже выставлять - ничего не помогло.:(
Есть еще возможные варианты?
    


Ответы

Ответ 1



Если кому интересно, то проблема была в SELinux. vi /etc/selinux/config или nano /etc/selinux/config И перезагрузить комп sudo reboot

Ответ 2



я не парился и добавил алиас на composer который выполняется от www-data sudo www-data -c 'composer app/console' вроде такого.

Symfony ChoiceType с загрузкой в него Entity из базы с помощью Ajax

#php #ajax #symfony


Задача: форма регистрации, кроме всего прочего есть три выпадающих списка. В первом
выбирается страна, после этого во второй Ajax'ом загружаются регионы и, при выборе
региона, в третий грузятся города. Все три поля грузят данные из трёх моделей: Country,
Region, City.

Код buildForm:

$builder
            ->add('country', EntityType::class, ['class' => 'AppBundle:Country',
                'choice_label' => 'name', 'placeholder' => '--- Выберите страну ---'])
            ->add('region', RegionSelectorType::class, [
                'required' => false])
            ->add('city', EntityType::class, ['class' => 'AppBundle:City', 'choice_label'
=> 'name', 'placeholder' => '--- Выберите город ---', 'required' => false])
            ->add('post_code', null, ['required' => false])
            ->add('address', null, ['required' => false])


Страна грузится сразу из сущности, их там немного. А вот для регионов и городов я
хотел сделать динамическую загрузку, чтобы не грузить зря кучу данных.

Пока застопорился на регионе, город будет по тому же принципу. Проблема в том, что
при отправке формы не происходит трансформация поля, по ID, в сущность. Пробовал и
Using Transformer, Creating a Reusable issue_selector Field, в профилере пишется


  Unable to reverse value for property path "region": The choice "15"
  does not exist or is not unique


Код моего типа RegionSelectorType:

namespace AppBundle\Form;

use AppBundle\Form\DataTransformer\RegionToNumberTransformer;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class RegionSelectorType extends AbstractType
{
    private $manager;

    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new RegionToNumberTransformer($this->manager);
        $builder->addModelTransformer($transformer);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'invalid_message' => 'Выбранный регион не существует',
        ));
    }

    public function getParent()
    {
        return ChoiceType::class;
    }
}


Код трансформера:

namespace AppBundle\Form\DataTransformer;

use AppBundle\Entity\Region;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class RegionToNumberTransformer implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * Transforms an object (region) to a string (number).
     *
     * @param  Region|null $region
     * @return string
     */
    public function transform($region)
    {
        if (null === $region) {
            return '';
        }

        return $region->getId();
    }

    /**
     * Transforms a string (number) to an object (region).
     *
     * @param  string $regionNumber
     * @return Region|null
     * @throws TransformationFailedException if object (region) is not found.
     */
    public function reverseTransform($regionNumber)
    {
        // no region number? It's optional, so that's ok
        if (!$regionNumber) {
            return;
        }

        $region = $this->manager
            ->getRepository('AppBundle:Region')
            // query for the issue with this id
            ->find($regionNumber)
        ;

        if (null === $region) {
            // causes a validation error
            // this message is not shown to the user
            // see the invalid_message option
            throw new TransformationFailedException(sprintf(
                'An region with number "%s" does not exist!',
                $regionNumber
            ));
        }

        return $region;
    }
}


Сервис регистрируется так:

services:
    app.form.type.region_selector:
        class: AppBundle\Form\RegionSelectorType
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: form.type, alias: region_selector }


В общем, все по мануалу. Функция reverseTransform() трансформера вообще не срабатывает.
Стоит только заменить в getParent() ChoiceType::class на TextType::class, как в примере
все работает: reverseTransform() срабатывает, сущность создается. С EntityType вместо
моего типа тоже все работает. Создаю регион типа EntityType, в choices подсовываю пустой
массив, - ошибка. Т.е., в поле формы должен присутствовать EntityType тот, что потом
будет возвращен сабмитом.

Первое что приходит в голову, создавать EventListеner, отлавливать передаваемое ChoiceType'ом
значение и создавать на лету сущность, но зачем тогда DataTransformer'ы?

Symfony использую 3, но, думаю, на второй будут примерно те же проблемы и решение.
    


Ответы

Ответ 1



но зачем тогда DataTransformer'ы? DataTransformerы тут ни при чём. Первое что приходит в голову, создавать EventListеner Как вы сами верно заметили, можно создавать EventListеner. Но не обязательно использовать ChoiceType, можно использовать также EntityType. Ниже примеры кода: Форма регистрации: namespace AppBundle\Form; use AppBundle\Entity\City; use AppBundle\Entity\Country; use AppBundle\Entity\Region; use Doctrine\ORM\EntityRepository; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; class RegistrationForm extends AbstractType { public function buildForm( FormBuilderInterface $builder, array $options ) { $builder ->add('country', EntityType::class, [ 'class' => Country::class, ]) ->add('region', EntityType::class, [ 'class' => Region::class, 'query_builder' => function(EntityRepository $er) { $qb = $er->createQueryBuilder('r') ->where('r.country IS NULL') ; return $qb; }, ]) ->add('city', EntityType::class, [ 'class' => City::class, 'query_builder' => function(EntityRepository $er) { $qb = $er->createQueryBuilder('c') ->where('c.region IS NULL') ; return $qb; }, ]) ; $builder->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) { $data = $event->getData(); $form = $event->getForm(); /** @var $country Country */ $country = $data['country']; $country = $country ? $country->getId() : false; /** @var $region Region */ $region = $data['region']; $region = $region ? $region->getId() : false; $this->modifyForm($form, $country, $region); }); $builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) { $data = $event->getData(); $form = $event->getForm(); /** @var $country integer */ $country = (int)$data['country']; $region = (int)$data['region']; $this->modifyForm($form, $country, $region); }); } protected function modifyForm(FormInterface $form, $country, $region = null) { if ( $country ) { $form->add('region', EntityType::class, [ 'class' => Region::class, 'query_builder' => function(EntityRepository $er) use ( $country ) { $qb = $er->createQueryBuilder('r') ->where('r.country = :country') ->setParameter('country', $country) ->orderBy('r.name') ; return $qb; } ]); if ( $region ) { $form->add('city', EntityType::class, [ 'class' => City::class, 'query_builder' => function(EntityRepository $er) use ( $region ) { $qb = $er->createQueryBuilder('c') ->where('c.region = :region') ->setParameter('region', $region) ->orderBy('r.name') ; return $qb; } ]); } } } } По умолчанию, регионы и города будут пустые, добились этого посредством параметра quiery_builder. Если указана страна, то мы ловим это в eventListener, и меняем query_builder, чтобы получить регионы этой страны. Для городов тоже самое. Думаю, с остальными справитесь.

Symfony 3, удалить записи из двух таблиц

#php #symfony #symfony3 #doctrine2


Здравствуйте, мне нужно удалить записи из двух таблиц. Есть таблица orders которая
связана по типу один ко многим с таблицей order_item.
Нужно по некоторой выборке записей из orders удалить соответствующие запитси в order_item.

public function deleteOrders()
{
    $dayClear = new DateTime('-2 days');

    return
        $this->createQueryBuilder('o')
            ->delete('AdminBundle:Order', 'o')
            ->delete('AdminBundle:OrderItem', 'oi')
            ->leftJoin('AdminBundle:OrderItem', 'oi', 'WITH', 'oi.order_id = o.id')

            ->where('o.total IS NULL')
            ->andWhere('o.updated <= :dayClear')
            ->setParameter('dayClear', $dayClear)
            ->getQuery()
            ->getResult();

}


Я реализовал такой метод для удаления. но он не рабочий, при этом когда я комментирую
строку

->delete('AdminBundle:OrderItem', 'oi')


то данные из первой таблице удаляются.
В чем может быть проблема и как решить задачу? Заранее спасибо!
    


Ответы

Ответ 1



Если реализовывать через DQL, думаю проще будет в первую очередь нужно найти ids. И потом можно сделать приблизительно так: $this->createQueryBuilder('o') ->delete() ->from('AdminBundle:Order o, AdminBundle:OrderItem oi') ->whereIn('o.id', '?', $ids) ->whereIn('o.order_id', '?', $ids) ->getQuery() ->getResult();

Как убрать _local из url для дефолтного языка

#symfony #symfony3


подскажите пожалуйста.
Реализовал мультиязычность для сайта, но нужно убрать в урле приставку /en для дефолтного
языка. Как это сделать?
Например есть урлы: 

site.com/en/login -> site.com/login(убераеться _locale), 
site.com/fr/login -> site.com/fr/login(остаеться _locale)

    


Ответы

Ответ 1



Я нашел решение которое мне подходит.Нужно установить бандл JMSI18nRoutingBundle Вот урок как настраивать сконфигурировать бандл. (Сыылка на видео) с 6-й минуты jms_i18n_routing: default_locale: "%locale%" locales: [ru, ua] strategy: prefix_except_default (тут важно поставить именно такой параметр)

понедельник, 6 января 2020 г.

Динамическое изменение requirements для route-а. Symfony 3.3

#php #url #symfony2 #symfony #symfony3


Возможно ли динамически изменять параметр requirements для @Route ?

Что я имею ввиду:


В базе имеется список услуг, у который есть свой url (service1, service2 и т.д)
Имеется шаблон, который будет использоваться в данном случае.


Имею подобный Action:

/**
 * @Route(
 *     "/{service_url}/",
 *     requirements = {
 *         "service_url": "service1|service2|service3|service4"
 *     }
 * )
 */
public function blablaAction($service_url)
{
    ...code...
}


Могу ли я данный параметр изменять динамически? 

Т.е. добавил новую услугу в базе, получаю url новой услуги и добавляю его в параметр
requirements.
Можно, конечно, каждый раз "руками" добавлять новую услугу, но это будет довольно
неудобно, т.к. хочется, чтобы подобное действие в дальнейшем происходило без участия
программиста.
    


Ответы

Ответ 1



Естественно это возможно. Вернее так, я думаю это естественно возможно, но сам этого не делал. Давайте по порядку. В одном из ответов ссылались на Symfony CMF и их динамический роутер. Если открыть эту страницу документации вы увидите что там пишут в общем то о том, о чем я вам напишу ниже. Вот что пишут там https://symfony.com/doc/3.3/routing/routing_from_database.html Это не магия, это попросту кастомный лоадер. Это вообще говоря не проблема и никогда проблемой не было. Сейчас я Вам все объясню. Смотрите. Symfony - крайне гибкая система. По сути своей Symfony - это набор независимых компонентов. Вам нужно внимательнее изучить компонент Routing. Если внимательно прочитать документацию, то можно заметить что вы, например, можете создать свой, "кастомный", загрузчик роутов (обзову их по-русски именно так). И вот понимая что вы можете создать свой загрузчик, вы понимаете что можете загружать роуты из любого места и они у вас могут быть любой конфигурации. Будь то файл, будь то база данных, будь то что то пришедшее из космоса и естественно ваши роуты могут реагировать на состояние вашей системы, хоть температуру окружающей среды. Так же вам нужно понять что аннотации - это одно из описаний роутов которые подгружаются загрузчиком роутов... правильно! который загружает роуты описанные в аннотациях. Давайте теперь ближе к делу. Вам нужно сделать роуты, которые зависят от моделей. Нет ничего проще! Открываете документацию вот тут . Смотрите как создается кастомный Loader, создаете сервис с тэгом routing.loader и добавляете в описание своих роутов в (routing.yml). Все! В этот сервис вы можете добавить все что угодно и описывать роуты как угодно. Слева, справа, сверху и снизу! Не забудьте просто убрать существующие аннотации в контроллере и управляйте своими роутами в вашем собственном Loader-е Имеем в сухом остатке. Создаете свой лоадер согласно документации. (В его конструктор вы можете добавить EntityManager) Описываете роуты взависимости от ваших пожеланий (забирая данные из того же EntityManager) Добавляете его в routing.yml Радуетесь. Еще раз ссылка на документацию, она живет здесь https://symfony.com/doc/3.3/routing/custom_route_loader.html p.s. Последнее. согласно документации The routes defined using custom route loaders will be automatically cached by the framework. So whenever you change something in the loader class itself, don't forget to clear the cache. Это не должно сбивать вас с толку. Естественно что вся логика внутри сервиса остается динамической, но кэш надо будет чистить после изменений (я так понимаю что в dev режиме тоже)

Ответ 2



Такое возможно. Но только нужно что б@Route может состоять из имени урла (имя не изменяется) и его динамической части /services/{service_url}/. Как показано в примере по ссылке выше, правило будет выглядеть так: // src/AppBundle/Controller/ArticleController.php // ... class ArticleController extends Controller { /** * @Route( * "/articles/{_locale}/{year}/{slug}.{_format}", * defaults={"_format": "html"}, * requirements={ * "_locale": "en|fr", * "_format": "html|rss", * "year": "\d+" * } * ) */ public function showAction($_locale, $year, $slug) { } } В Вашем же случае должно быть как то так: /** * @Route( * "/services/{_service_url}/", * defaults={"_service_url": "sevice1"}, * requirements={ * "_service_url": "service1|service2|service3|service4" * } * ) */ public function blablaAction($_service_url){...} То есть необходимо наличие имени урла перед динамической частью.

Ответ 3



Динамически менять requirements не получится, так как этот параметр компилируется в кэш-файл и должен быть независим от внешних источников типа базы данных, так как скомпилируется единожды, затем будет использоваться скомпилированный файл. В проекте Symfony CMF решили немного исправить эту проблему и создали свой вариант роутера, который не кэшируется и всегда проверяет все условия в ран-тайме. Таким образом, они создали динамический роутер, который по данным из базы данных отдает нужную страницу. Подробнее про этот роутер можно прочитать здесь. Кроме того, если нужно просто отсеить все url-ы, которых нет в базе, то можно в самом контроллере запросить в БД нужный url и в случае, если он не найден, выдать ответ 404: /** * @Route( * "/{serviceUrl}/", * requirements = { * "serviceUrl": ".+" * } * ) */ public function blablaAction($serviceUrl) { $servicePage = $this->getRepository(ServicePage::class)->findBy(['url' => $serviceUrl]); if (!$servicePage) { return $this->createNotFoundException('Service url /' . $serviceUrl . ' was not found'); } ...code... }

Ответ 4



Вам это не нужно. Такой подход в корне неверен. Вам нужно воспользоваться банальным подходом (который был предложен выше, это /services/{serviceId}/) и проверять услугу внутри контроллера, там вы сможете сделать какие угодно проверки с услугами. В требованиях к идентификатору услуги можно оставить только regexp. Если вы попытаетесь реализовать выбранную вами схему, то вы пойдёте против системы и фреймворка, и обречёте себя, и следующих программистов, на постоянную боль от исправления багов в роутах и поддержку этого гиблого решения.

пятница, 3 января 2020 г.

Ошибка подключение к БД в symfony

#php #symfony2 #symfony #symfony3


Вылил сайт на хостинг и появилась ошибка подключения к базе данных.


  You have requested a non-existent parameter "database_name". Did you mean one of
these: database


Локально всё работает нормально. В чём может быть ошибка?
    


Ответы

Ответ 1



Скорее всего неправильно задан конфиг в parameters.yml либо в config.yml. в parameters.yml добавьте: parameters: database_host: YOUR_HOST database_port: 3306 database_name: DB_NAME database_user: DB_USER database_password: DB_PASS а в config.yml добавьте подключение к доктрине doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: '%database_host%' port: '%database_port%' dbname: '%database_name%' user: '%database_user%' password: '%database_password%' charset: UTF8

среда, 1 января 2020 г.

Symfony 3, разный редирект после авторизации для разных ролей

#php #symfony #symfony3


У меня есть две роли

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN


Мне нужно чтобы для пользователейпосле после авторизации с ролью ADMIN был редирект
в /admin
А для пользователей с ролью USER был редирект на /user
Сейчас в файле security у меня так:

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_token_generator: security.csrf.token_manager
            login_path: /login
            check_path: /login_check
            always_use_default_target_path: false
            default_target_path:            /admin

        logout:       true
        anonymous:    true


Как мне нужно модифицировать security или ещё что-то добавить, чтобы решить задачу?
    


Ответы

Ответ 1



В разделе firewalls вы должны иметь 2 подраздела. Один для обычных клиентов а второй для менеджеров. И вы можете дать группу страниц которые должны быть доступны для конкретной группе клинентов с помощью pattern. Например pattern: /admin(.*) В итоге у вас должно получиться такой config firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: /login_check always_use_default_target_path: false default_target_path: /user logout: true anonymous: true admin: pattern: /admin(.*) form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: /admin/login_check always_use_default_target_path: false default_target_path: /admin logout: true anonymous: true

Ответ 2



Если нужно использовать один firewall (например, чтобы авторизованный админ на фронте тоже был авторизован), то можно использовать success_handler в firewall SecurityBundle Configuration security.yml main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: fos_user_security_check failure_handler: user.authentication.failure_handler success_handler: user.authentication.success_handler services.yml services: user.authentication.success_handler: class: UserBundle\Security\AuthenticationSuccessHandler arguments: ["@router"] AuthenticationSuccessHandler.php class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { /** @var I18nRouter */ protected $router; public function __construct(I18nRouter $router) { $this->router = $router; } /** * {@inheritdoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { /** @var User $user */ $user = $token->getUser(); // Проверяем роль пользователя, генерим url через router, возвращаем ответ с редиректом return $response; } }

пятница, 27 декабря 2019 г.

Правильно ли добавлять в сущность посторонние методы в symfony

#php #ооп #symfony #symfony3 #best_practice


Изучаю symfony, использую версию 3.4
Возник такой вопрос. У меня есть таблица domains со списком доменов и соответственно
сущность для этой таблицы с полями таблицы и геттерами-сеттерами для них.
Появилась необходимость выяснить в коде, есть ли у домена кириллические символы (русские
буквы). И возник вопрос, корректно ли будет с точки зрения best practices добавить
в сущность AppBundle\Entity\Domains метод вроде:

public function isCyrillic(){
    return preg_match('/[\p{Cyrillic}]/u', $this->name) === 1 ? true : false;
}


А потом добавлять в эту сущность ещё и ещё подобных методов? Или в сущности должны
храниться только описания полей таблицы и геттеры-сеттеры для них? А другие методы
нужно выносить в сервисы или ещё куда-то?
Интересует ответ именно best practices, т.к. хочется писать код корректно и не лепить
велосипеды. Нужно мнение профессионала)
    


Ответы

Ответ 1



Приведенный вами метод вполне укладывается в представление Enitiy. Туда подходит всё что может содержать префикс is|get|set|has и прочие. Сервисы могут иметь подобные методы, но сами они stateless, поэтому придётся на вход подавать эту самую сущность, что не очень практично. Репозитории так же сам по себе являются stateless, и служат для работы уже с самими сущностями, так что туда тоже не стоит относит подобные методы.

Ответ 2



Это нарушит принцип SRP. Класс не должен иметь несколько обязанностей. Обязанность данного класс - хранить и получать данные. Метод isCyrillic добавляет классу новую обязанность. А это может привести к дублированию кода и увеличению сложности класса. Вы не сможете воспользоваться этим методом в других местах или вообще в других проектах. Поэтому я бы вынес этот метод в отдельный сервис.

воскресенье, 22 декабря 2019 г.

Как правильно организовать мультиязычность Symfony4

#php #symfony #symfony3 #symfony4


Сталкнулся c непониманием, как можно организовать мультиязычность в symfony4. Идея
такая, есть адрес, например site.com. Если он без префикса локали, брать дефолтную
локаль, если он например site.com/en/, брать английскую локаль. Как правильно сделать
так, что бы локаль сетилась из префикса, а соответсвтенно подтягивались все переводы
и т.д. Ну и, если есть возможность, все урлы были с префиксом.
    


Ответы

Ответ 1



Как указывал @u_mulder выше в документации. В symfony есть бандл Translations. И весь механизм сводится к таким пунктам. настройка translations; включение локали в URL; Базовый перевод; Создать файлы перевода для каждой поддерживаемой локали; перевод в шаблоне. Настройка translations. Установка composer require symfony/translation Настройка translations. Конфигурация В документации предлагают создать некий config/packages/translation.yaml, а потом его подключить в config.yaml. Я предлагаю прямо сразу в конфиге в секции framework добавить framework: default_locale: 'ru' translator: fallbacks: ['ru'] Где default_locale локаль по умолчанию, а fallbacks - это резервная локаль. То есть локаль на которую будет переведен ключ в случае, если нигде не нашлось перевода. Включение локали в URL Механизм поддерживается системой маршрутизации с использованием специального параметра _locale. Добавляем в рутовый конфиг роутинга следующее: # config/routes.yaml main: path: /{_locale} controller: App\Controller\MainController::index requirements: _locale: ru|en Теперь роутинг будет формироваться example.com/ru. А так как ru по умолчанию, то example.com должен сделать редирект на example.com/ru. Соответсвенно, обращение к какому-нибудь example.com/ru/home нужно добавить : # config/routes.yaml main: .... home: path: /{_locale}/home controller: App\Controller\HomeController::index requirements: _locale: ru|en Но если нам, допустим, понадобится, к примеру, example.com/ru/home/room. Опять писать правило только для другого метода HomeController? Нет, в symfony можно настроить это глобально: # config/routes.yaml main: resource: "@AppBundle/Resources/config/routing.yml" prefix: /{_locale} requirements: _locale: ru|en defaults: { _locale: ru} Базовый перевод; этот пункт для случаев если нужно переводить прямо в коде. //MainController use Symfony\Contracts\Translation\TranslatorInterface; public function index(TranslatorInterface $translator) { $translated = $translator->trans('Some text'); // ... } Создать файлы перевода для каждой поддерживаемой локали По умолчанию Symfony ищет переводы в: translations/ в корне проекта; src/Resources/BUNDLE_NAME/translations/ в конкретном бандле depricated; Resources/translations/ в папке ресурсов. Также важно указать имя файла перевода. По умолчанию создайте файлы в папке translations/ messages.ru.yaml и messages.en.yaml. Ну и заполняем словари: # translations/messages.ru.yaml Some text: какой-то текст Hello world: привет мир ///////////////// # translations/messages.en.yaml Some text: кSome text Hello world: Hello world Как формируется правила создания файла перевода, настройка пути - все это можно почитать тут. Перевод в шаблоне Ну и в шаблоне (twig файле) переводим так: {{ message|trans }} Полезная информация: - управлять локалью для сессий пользователя; - переводы в шаблонах; - Как работать с локалью пользователя; - материалы на русском (не уверен что будет работать, но существенно упростит понимание некоторых моментов)

воскресенье, 24 ноября 2019 г.

Как устроить ловушку для хакера, или достойно отбивать атаки?


Ребята выручайте. Меня взломали и в наглую соединились со мной, требуя денег. Я новичок в этом деле и думаю, что пока научусь, то офис скорее снимет меня с работы.

Недавно сайт стал зависать, похоже было на DDOS атаку. Забанил его по IP, но бесполезно
Я устал бегать за IP и банить их, да и в принципе это не выход. Просто когда с хакеро
переписывался, он сделал ряд проколов, сказав, что может сломать даже мою базу данных. Я когда проверял базу во время перегрузок, то на нее никаких нагрузок не было, в основном на сервер. Меняю всякий раз все возможные пароли, но хакер  беспрепятственно обходит их.

И так, шаря, да выискивая слабые места, наткнулся на то, что мой сервер выдает страниц
не только по index.php, но и по abc.php, xyz.php. Не знаю, блин, но носом чую, что гад припрятал какой-то файл и обращается к нему. Где и идут тормоза, заполняя канал на 100%. Базу удалить, в принципе, можно будет изнутри этого файла (DELTE FROM tbl_name).

Как можно найти этот файл, или как можно понять какой-то необычный вход на сервер
У меня Symfony 1.4 PHP фреймворк. Сайт 5 летней давности. Писать его заново? (не вариант, по крайней мере не сейчас). Что я пропустил на уровне хранения лишнего файла? Или не в ту сторону копаю?

Я слышал от друзей что в 90 % за этим стоят конкуренты. И в обратку хакнув его, чащ
всего ддос прекращается. Но мысль навредить кому-то из за своей слабости чего-то не вдохновляет.

Попросил хакера дать время, чтоб якобы уболтать начальство расскошелиться.
    


Ответы

Ответ 1



В принципе не важно вас взломали,или пытаются взломать,ведь рано или поздно мы сталкнёмся с этой угрозой. Всe действия описанные ниже помогут узнать о ваших слабых и уязвимых местах, помогу исправить допущенные ошибки, помогут вам грамотно защищаться и в дальнейшем эффективно бороться с этим злом. Научимся методике и технологиям устраивании ловушек для злоумышленников (Honeypot - горшочек с медом). Приведу действия первой необходимости: Если вас уже взломали: Меняем логины и пароли серверов (Linux, MySQL, .....). Убеждаемся что у нас как минимум две группы пользователей с разными привилегиями.Допусти web и root, где web эта привилегия стоит для всех пользователей с ограниченными возможностями(Запре на закачку файлов кроме image type). Как правильно дать привилегии ? Читаем Как Повысить безопасность и удобство использования Вашего сервера и заложить прочную основу для последующих действий.. Если GIT не показывает необыкновенные изменения,то может быть стоит заглянуть в т директории которые вне него.Чаще всего это те директории куда загружаются изображения или иные файлы которые позволяем пользователям загружать. find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *( --color Эта команда найдет php файлы содержащие eval(str_rot13(base64_decode( (Также можно искать и в базе данных SELCT col_nam FROM tbl_name WHERE col_name LIKE '%eval(str_rot13(base64_decode(%'). Синтаксис grep очень прост и вы можете изменить его под свои нужды. На уровне PHP: **Ограничивать использование опасных php функций в php.ini ** (disable_functions = "show_source, system, shell_exec, exec, eval" ).Можно закрыть mail() функцию.и зафиксировать обращение к SMTP через сокетное соединение на 25 порт. Тут обращу внимание на функцию eval. Если каким то образом в вашем коде припрята PHP код то его исполнение через eval не произойдет.Этот список можно дополнять или убавлять по необходимости.Все отключили любые PHP скрипты которые были написаны надеюсь не нами. Межсайтовая подделка запроса (CSRF (англ. Сross Site Request Forgery )): Много популярных фреймворков имеют полноценную защиту от него в том числе и ваш.Распространённы способом защиты является механизм, когда с каждой сессией пользователя ассоциируетс дополнительный секретный ключ,и при отправки запроса в месте с параметрами и отправляется сгенерированный токен.А потом сравниваются сгенерированный токен и токен пришедший с запросом,если совпадают то этот запрос неподделанный. Эффективен для выполнения POST, PUT, DELETE, STORE-запросов. Межсайтовый скриптинг XSS (англ. Cross-Site Scripting). Выводить текст сохраненной не вами на страницу так как его вводили.Тут есть нюансы. Если пользователь сохраняет текст (К примеру оставляет комментарий, или делает поис по сайту) у вас в базе или еще где нибудь, то надо учесть что если нужен только текст тогда до сохранения очистить его от нежелательных тeгов(Для PHP strip_tags — Удаляет HTML и PHP-теги из строки). Если все таки нужно пропускать теги то сделать какие нибудь предварительные валидации.Ил вводить их маркируя по принципу stackoverflow textarea.Мы же публикуя вопрос или ответ не можем же вводить любой тег.Просто забыл как называется такие типы маркировки текста :) Всегда тщательно проверяйте файлы которые загружаются на сервер через форму или каки нибудь способом.Проверяйте их расширения и содержимое.Часто загрузка файлов без обеспечени надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывае практика, стали настоящей проблемой в веб-приложениях на PHP.Чтобы удостовериться, чт это действительно изображение не используйте getimagesize() для проверки того, что файл является файлом с изображением. Для этих целей используйте расширение Fileinfo. Стоит добавить, что желательно сделать приведение файла к конкретному формату, например png. При приведении метаданные картинки потеряются, обеспечив практически гарантируемую безопастность.Наличие в загрузке файлов с расширением типа .php нужно проверять вообще в начале работы сайта, и если они есть сразу же их отбрасывать. На уровне .htaccess Ограничивать точки входа на сайте. Например в фреймворках в основном доступ идет через index.php.Или других вами известны файлах (admin.php,back.php, ...). Всегда можно отследить обращение к другому файлу, и всегда можно логировать информацию об обращениях к подозрительному файлу в отдельном журнале. проверьте .htaccess файлы на подозрительные изменения.auto_append_file и auto_prepend_fil включают другие PHP файлы в начале или в конце всех PHP скриптов, злоумышленники могут использовать их для включения своего кода. find . -type f -name '\.htaccess' | xargs grep -i auto_prepend_file; Следующая команда ищет во всех подкаталогах файлы .htacсess, которые содержат 'http' Результатом поиска будет список всех правил перенаправлений, в которых могут быть и вредоносные правила find . -type f -name '\.htaccess' | xargs grep -i http; . Во все каталоги, доступные для записи добавляем файл .htaccess со следующим содержимым: php_flag engine 0 RemoveHandler .phtml .php .php2 .php3 .php4 .php5 .php7 .phps .cgi .pl .asp .aspx .shtml .shtm .fcgi .fpl .htm .html AddType text/plain .phtml .php .php2 .php3 .php4 .php5 .php6 .php7 .phps .cgi .pl .asp .aspx .shtml .shtm .fcgi .fpl .htm .html Этим самым мы отключаем PHP в данном каталоге и заставляем все скрипты отображаться как HTML. Это можно сделать просто на всякий случай. Лишним уж точно не будет. Или запрет на исполнение: Order Allow,Deny Deny from all На уровне баз данных,частностью MySQL: Всегда пользуйтесь Подготовленными запросами и хранимыми процедурами: Большинство баз данных поддерживают концепцию подготовленных запросов. Что это такое Это можно описать, как некий вид скомпилированного шаблона SQL запроса, который будет запускаться приложением и настраиваться с помощью входных параметров. У подготовленных запросов есть два главных преимущества: Запрос необходимо однажды подготовить и затем его можно запускать столько раз, сколько нужно, причем как с теми же, так и с отличающимися параметрами. Параметры подготовленного запроса не требуется экранировать кавычками; драйвер эт делает автоматически. Если в приложении используются исключительно подготовленные запросы разработчик может быть уверен, что никаких SQL инъекций случиться не может (однако, если другие части текста запроса записаны с неэкранированными символами, SQL-инъекции все же возможны; здесь речь идет именно о параметрах). Защищайтесь от SQL-инъекции Прямое внедрение вредоносных инструкций в SQL-запросы - это методика, в которой взломщи создает или изменяет текущие SQL-запросы для отображения скрытых данных, их изменени или даже выполнения опасных команд операционной системы на сервере базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из пользовательского ввода и статических параметров. На уровне системы Linux ... Лучше этих сервисов, которые реально защищают от DDOS, я пока не знаю.Пользуюсь ими.Пока что отбивают :).Это Cloudflare ,и Incapsula Как устроить ловушку для хакера (Honeypot - горшочек с медом): Не занимайтесь этим если у вас нет достаточных знаний и квалификации, хакер может победить вас в вашей же ловушке. Honeypot (горшочек с медом) давно широко используется в мире компьютерной безопасности.Это ресурс, задача которого отдаться хакеру, цель которого принять тест, атаку и быть взломанным. Это может быть эмулятор другой системы или приложения, некая "темница с засадой" или просто стандартная система. Как бы вы не построили свой горшочек, главная его задача — подвергнутся нападению и рассказать вам в подробностях об этом. Quick and Simple PHP Honey Pot Spam Prevention Simple PHP HoneyPot Tutorial Изучить инструменты, тактику и мотивы, связанные с компьютерными и сетевыми атаками, и поделиться извлеченными уроками. Естественно все в этом посте перечислить невозможно.Но если попытаться реализоват все что в этом посте перечислено,то можно научиться защищаться и не хило.По каждому из пунктов можно всегда задать вопрос или поискать больше информации для более детальной и правильной ее реализации. Полезные материалы : Веб-сервисы для проверки сайтов на вирусы https://habrahabr.ru/post/303956/ Методы борьбы с DDoS-атаками https://habrahabr.ru/post/129181/ 5 советов по борьбе с DDOS-атаками http://www.securitylab.ru/analytics/442099.php Устоять любой ценой: методы борьбы с DoS/DDoS-атаками https://xakep.ru/2009/10/14/49752/ 5 программ для анализа безопасности Вашего сайта https://seo-zona.ru/5-programm-dlya-analiza-bezopasnosti-vashego-sajta-2015-03-31.html Как понять что ваш сайт был взломан https://www.siteguarding.com/ru/kak-poniat-chto-vash-sait-byl-vzloman Бесплатный онлайн-сканеры вирусов: Веб-сканер QUTTERA https://quttera.com/ Веб-сканер ReScan.pro https://rescan.pro/ VirusTotal https://www.virustotal.com/ru/ Веб-сканер Sucuri https://sitecheck.sucuri.net/ Онлайн—сканеры Dr.Web https://vms.drweb.ru/online/ Вооружайтесь знаниями. Будьте бдительней.. Удачи :)

Ответ 2



Как минимум сделай это Сделай бэкапы всего Ищи в проекте новые файлы по дате Проверь где-то свои исходники, мб по уже существующей сигнатуре вируса найдет что-то. И самое главное, не понятно по какой причине вы еще используете Symfony 1.4. Я думаю возможно есть баг в этой версии или у вашем коде. Посмотрите места там где у вас загружаются файлы. Поставьте модуль для Nginx (если он стоит, если нету, ставьте) модуль для анти ддоса. Вот статья https://habrahabr.ru/post/139931/ Соглашусь с комментариями, поищите в проекте grep'ом eval

Ответ 3



Заранее извините за советы на уровне КО. Однако... Обратите внимание на специфику вашего проекта. Если ваши клиенты из России, обрубит все иностранные ip. Очень вероятно, что злоумышленник ходит к вам через зарубежный прокси. Предлагаю разместить на главной форму интересную для злоумышленника, но не интересну для клиентов. Например, вход для дилеров/оптовиков/партнеров. Скорее всего злоумышленник попытается атаковать новую форму, засветив свой ip. Оцените вероятность внутренней угрозы. Возможно ли, что это кто-то из сотрудников организации? Попробуйте публичные сканеры безопасности, типа таких https://observatory.mozilla.org/ Конечно эти сервисы достаточно параноидальны и не все нужно внедрять на рабочих проектах. Но может быть вам удастся закрыть какие-либо дыры. И на мой взгляд хорошо бы поставить в известность руководство. Возможно это поможет найти средства на платный аудит безопасности.

пятница, 12 июля 2019 г.

В symfony не получается сделать if is_page(current_page) проверку по странице (

app.request.get('_route')
{% if app.request.get('_route') == 'road-construction' %} My Link {% endif %}
Не работает( Это динамическая страница и у них общий шаблон( У страниц таких общий шаблон индекс но через админку была создана страница динамическая и так как можно разделить динамические ????


Ответ

{% if '/company/road-construction' in app.request.uri %} Open modal

Modal dialog


Закрыть

{% endif %}

среда, 10 июля 2019 г.

Отображение в режиме production для Symfony 3

Здравствуйте!
Делаю тест на Symfony 3 (до этого работал с Laravel).
Никак не могу понять, как настроить отображение контента в prod-окружении. Маршруты через app_dev.php отображаются нормально, а без него возвращается 500 ошибка.
Подскажите, пожалуйста, где копать? Информации по этому вопросу на официальном сайте пока найти не удалось, а сроки поджимают.
В логе следующее:
[2016-04-18 09:13:08] request.ERROR: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for "GET /address"" at D:\webdev\symfony\site.lc\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\EventListener\RouterListener.php line 123 {"exception":"[object] (Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException(code: 0): No route found for \"GET /address\" at D:\\webdev\\symfony\\site.lc\\vendor\\symfony\\symfony\\src\\Symfony\\Component\\HttpKernel\\EventListener\\RouterListener.php:123, Symfony\\Component\\Routing\\Exception\\ResourceNotFoundException(code: 0): at D:\\webdev\\symfony\\site.lc\\var\\cache\\prod\\appProdUrlMatcher.php:46)"} []


Ответ

Итак, всё дело в кэше.
Поскольку prod среда оптимизирована для скоростной работы, то конфигурация, маршрутизация и Twig-шаблоны компилируются в голые PHP-классы и кэшируются. Если вы изменили что-либо в dev среде и хотите посмотреть как это выглядит в prod среде, то вам нужно очистить кэш этой среды (prod); если этого не сделать, то вы увидите то, что откомпилировалось и закэшировалось ранее.
Очистить кэш в Symfony можно с помощью консоли:
php bin/console cache:clear
Команда выше очистит кэш dev среды, так как по умолчанию консольные команды выполняются в ней (dev среде)
Чтобы очистить кэш для prod или другой среды, нужно добавить соответствующую опцию:
php bin/console cache:clear --env=prod
Альтернативный вариант:
php bin/console cache:clear -e prod
Источники:
The Symfony Book → Configuring Symfony (and Environments) → #Environments The Symfony Cookbook → Recipes about Console → How to Use the Console

Медленный ли Symfony?

В данный момент, решил попробовать Symfony 3 на PHP 7, и задаюсь вопросом производительности.
Есть задача написания REST API, решил попробовать Symfony 3, написал тестовое API и попробовал выполнить тест Apache AB (ab -t 10 -c 10) на несуществующий метод, скорость обработки 2062 запроса за 10 секунд или 206 запросов в секунду.
Делаю тоже самое на Phalcon, скорость 23297 запросов за 10 секунд или 2329.69 запросов в секунду. Если запускать один запрос, то скорость одинаковая, примерно 90 мс.
В чем прикол? Может я что-то делаю неправильно и где-то нужно настроить что-то, чтобы на несуществующий запрос была более высокая скорость или это нормальная скорость? Я понимаю, что Symfony имеет высокую абстракцию, за нее нужно платить, и поэтому производительность меньше, но тут просто нужно просто вывести 404 ошибку и такой сумасшедший отрыв.
Отрыв Phalcon становится меньше, если взять и добавить операцию поиска в базу и маппинга, через модель встроенную в фреймворк. Phalcon правда всеравно быстрее, 1600 запросов против 900 запросов Symfony за 10 секунд.
Конфигурация: PHP 7, Debian, opcache on, Symfony3, Phalcon 3, Кеш Symfony включен, режим Production.
Подключенные бандлы в Symfony:
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new AppBundle\AppBundle(), new FOS\RestBundle\FOSRestBundle(), new JMS\SerializerBundle\JMSSerializerBundle(), new Nelmio\CorsBundle\NelmioCorsBundle()
app.php:
use Symfony\Component\HttpFoundation\Request;
/** * @var Composer\Autoload\ClassLoader */ $loader = require __DIR__.'/../app/autoload.php'; include_once __DIR__.'/../var/bootstrap.php.cache';
$kernel = new AppKernel('prod', false); $kernel->loadClassCache(); $kernel = new AppCache($kernel);
// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter Request::enableHttpMethodParameterOverride(); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response);

Ладно, делаем замеры потребляемых ресурсов при выполнении запроса в базу данных на поиск и маппинг
Выполняем замер Symfony и существующей конфигурации PHP-FPM при работе Apache AB (ab -t 10 -c 10):
20383 www-data 20 0 380884 26040 18020 R **58,3** 0,3 0:10.35 php-fpm7.0 21394 www-data 20 0 380884 26040 18020 R **57,3** 0,3 0:03.62 php-fpm7.0 21498 www-data 20 0 380884 25908 17900 R **57,3** 0,3 0:02.77 php-fpm7.0 19479 www-data 20 0 380884 25020 18020 D **55,7** 0,3 0:15.08 php-fpm7.0 20481 www-data 20 0 380884 26044 18020 R **52,0** 0,3 0:09.30 php-fpm7.0
Окей, в среднем FPM жрет 52 процента ядра на каждый процесс, делаем замер Phalcon:
24110 www-data 20 0 379016 17876 12848 S **13,6** 0,2 0:03.57 php-fpm7.0 25593 www-data 20 0 378884 17776 12848 R **13,3** 0,2 0:02.30 php-fpm7.0 27023 www-data 20 0 378884 17608 12788 S **13,3** 0,2 0:01.08 php-fpm7.0 25445 www-data 20 0 378884 17780 12848 S **13,0** 0,2 0:02.48 php-fpm7.0 27177 www-data 20 0 378884 17600 12788 R **13,0** 0,2 0:00.91 php-fpm7.0
Phalcon не грузит систему, при одинаковых действиях, загрузка на каждый процесс 13 процентов.
Я могу предположить, что возможно скорость меньше и нагрузка выше из-за того, что Symfony дергает кеш с диска каждый раз, а Phalcon по умолчанию все пишет в память. Если это так, то как перенести весь кеш в память, чтобы исключить нагрузку на диск?
Кто разбирается в Symfony, скажите, как сделать его быстрее и возможно ли это? В чем ошибка?


Ответ

фалькон быстрый потому, что написан как расширение для PHP на С
Да, симфони очень медленный, вовсе не по тому, что "Symfony дергает кеш с диска каждый раз, а Phalcon по умолчанию все пишет в память.", а потому, что представляет собой достаточно толстую прослойку уймы абстракций.
Нет, невозможно. Они предназначены для разных задач. Удобство клепать мелкие сайты с модным MVC на Симфони vs условно-хардкорная производительность чистых сей для фалькона.
и нет, у вас не получится как-то супер-быстро разрешать нагрузку на на существующий урл, если все урлы обрабатывает симфони, если урл дошел от веб-сервера до симфони, она его еще как обработает. Придется решать проблему несуществующих урлов как-то по-другому (на стороне веб-сервера)
Сделать симфоню быстрее можно, наверное, настроив правильное кэширование (opcache), но тем не менее, с фальконом она не сможет соревноваться по скорости.
Т.е. даже симфоневый раутинг (я про 404) будет медленней фальконовского.
Кроме того, использование Апача в качестве сервера для хайлоада не oche рекомендуется (возможно, он, конечно, вырос за последние годы)
P.S. Как я уже говорил, 36 тысяч вызовов функции substr на один http запрос в Симфони... ну.. окей.

четверг, 20 июня 2019 г.

Symfony. Не удается подключить CSS/JS

Установил Symfony 3.0.4, в каталоге web разместил папку css с файлами стилей. В base.html.twig прописал:
{% block stylesheets %} {% endblock %}
Но когда перехожу обновляю страницу, в консоле пишет что мой app.css 404 not found. Я перечитал всю документацию, посмотрел кучу видео и прочитал много статей из неофициальных источников и этот способ работает везде! но только не у меня. Для убедительности установил symfony-demo проект и там тоже не работает, причем изначально там прописан такой же код что я написал выше. Может что-то не так с веб-сервером? я уже не знаю что делать. Исходников никаких нет, проделываю всё в новом (чистом) проекте. Ещё пробовал чистить кеш - не помогло.
Вот видео о том как подключить, у меня не работает этот способ. https://knpuniversity.com/screencast/symfony/layout-assets


Ответ

Когда добавлял virtualhost в apache, в качестве DocumentRoot указывал ../web/app_dev.php, а нужно было всю папку web, без файла.

понедельник, 18 марта 2019 г.

Symfony 3, удалить записи из двух таблиц

Здравствуйте, мне нужно удалить записи из двух таблиц. Есть таблица orders которая связана по типу один ко многим с таблицей order_item. Нужно по некоторой выборке записей из orders удалить соответствующие запитси в order_item.
public function deleteOrders() { $dayClear = new DateTime('-2 days');
return $this->createQueryBuilder('o') ->delete('AdminBundle:Order', 'o') ->delete('AdminBundle:OrderItem', 'oi') ->leftJoin('AdminBundle:OrderItem', 'oi', 'WITH', 'oi.order_id = o.id')
->where('o.total IS NULL') ->andWhere('o.updated <= :dayClear') ->setParameter('dayClear', $dayClear) ->getQuery() ->getResult();
}
Я реализовал такой метод для удаления. но он не рабочий, при этом когда я комментирую строку
->delete('AdminBundle:OrderItem', 'oi')
то данные из первой таблице удаляются. В чем может быть проблема и как решить задачу? Заранее спасибо!


Ответ

Если реализовывать через DQL, думаю проще будет в первую очередь нужно найти ids. И потом можно сделать приблизительно так:
$this->createQueryBuilder('o') ->delete() ->from('AdminBundle:Order o, AdminBundle:OrderItem oi') ->whereIn('o.id', '?', $ids) ->whereIn('o.order_id', '?', $ids) ->getQuery() ->getResult();

вторник, 22 января 2019 г.

Ошибка подключение к БД в symfony

Вылил сайт на хостинг и появилась ошибка подключения к базе данных.
You have requested a non-existent parameter "database_name". Did you mean one of these: database
Локально всё работает нормально. В чём может быть ошибка?


Ответ

Скорее всего неправильно задан конфиг в parameters.yml либо в config.yml.
в parameters.yml добавьте:
parameters: database_host: YOUR_HOST database_port: 3306 database_name: DB_NAME database_user: DB_USER database_password: DB_PASS
а в config.yml добавьте подключение к доктрине
doctrine: dbal: default_connection: default connections: default: driver: pdo_mysql host: '%database_host%' port: '%database_port%' dbname: '%database_name%' user: '%database_user%' password: '%database_password%' charset: UTF8

понедельник, 1 октября 2018 г.

Как устроить ловушку для хакера, или достойно отбивать атаки?

Ребята выручайте. Меня взломали и в наглую соединились со мной, требуя денег. Я новичок в этом деле и думаю, что пока научусь, то офис скорее снимет меня с работы.
Недавно сайт стал зависать, похоже было на DDOS атаку. Забанил его по IP, но бесполезно. Я устал бегать за IP и банить их, да и в принципе это не выход. Просто когда с хакером переписывался, он сделал ряд проколов, сказав, что может сломать даже мою базу данных. Я когда проверял базу во время перегрузок, то на нее никаких нагрузок не было, в основном на сервер. Меняю всякий раз все возможные пароли, но хакер беспрепятственно обходит их.
И так, шаря, да выискивая слабые места, наткнулся на то, что мой сервер выдает страницы не только по index.php, но и по abc.php, xyz.php. Не знаю, блин, но носом чую, что гад припрятал какой-то файл и обращается к нему. Где и идут тормоза, заполняя канал на 100%. Базу удалить, в принципе, можно будет изнутри этого файла (DELTE FROM tbl_name).
Как можно найти этот файл, или как можно понять какой-то необычный вход на сервер? У меня Symfony 1.4 PHP фреймворк. Сайт 5 летней давности. Писать его заново? (не вариант, по крайней мере не сейчас). Что я пропустил на уровне хранения лишнего файла? Или не в ту сторону копаю?
Я слышал от друзей что в 90 % за этим стоят конкуренты. И в обратку хакнув его, чаще всего ддос прекращается. Но мысль навредить кому-то из за своей слабости чего-то не вдохновляет.
Попросил хакера дать время, чтоб якобы уболтать начальство расскошелиться.


Ответ

В принципе не важно вас взломали,или пытаются взломать,ведь рано или поздно мы сталкнёмся с этой угрозой. Всe действия описанные ниже помогут узнать о ваших слабых и уязвимых местах, помогут исправить допущенные ошибки, помогут вам грамотно защищаться и в дальнейшем эффективно бороться с этим злом. Научимся методике и технологиям устраивании ловушек для злоумышленников (Honeypot - горшочек с медом).
Приведу действия первой необходимости:
Если вас уже взломали:
Меняем логины и пароли серверов (Linux, MySQL, .....). Убеждаемся что у нас как минимум две группы пользователей с разными привилегиями.Допустим web и root, где web эта привилегия стоит для всех пользователей с ограниченными возможностями(Запрет на закачку файлов кроме image type). Как правильно дать привилегии ? Читаем Как Повысить безопасность и удобство использования Вашего сервера и заложить прочную основу для последующих действий. Если GIT не показывает необыкновенные изменения,то может быть стоит заглянуть в те директории которые вне него.Чаще всего это те директории куда загружаются изображения или иные файлы которые позволяем пользователям загружать. find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color Эта команда найдет php файлы содержащие eval(str_rot13(base64_decode( (Также можно искать и в базе данных SELCT col_nam FROM tbl_name WHERE col_name LIKE '%eval(str_rot13(base64_decode(%'). Синтаксис grep очень прост и вы можете изменить его под свои нужды.
На уровне PHP:
**Ограничивать использование опасных php функций в php.ini ** (disable_functions = "show_source, system, shell_exec, exec, eval" ).Можно закрыть mail() функцию.и зафиксировать обращение к SMTP через сокетное соединение на 25 порт. Тут обращу внимание на функцию eval. Если каким то образом в вашем коде припрятан PHP код то его исполнение через eval не произойдет.Этот список можно дополнять или убавлять по необходимости.Все отключили любые PHP скрипты которые были написаны надеюсь не нами. Межсайтовая подделка запроса (CSRF (англ. Сross Site Request Forgery )): Много популярных фреймворков имеют полноценную защиту от него в том числе и ваш.Распространённым способом защиты является механизм, когда с каждой сессией пользователя ассоциируется дополнительный секретный ключ,и при отправки запроса в месте с параметрами и отправляется сгенерированный токен.А потом сравниваются сгенерированный токен и токен пришедший с запросом,если совпадают то этот запрос неподделанный. Эффективен для выполнения POST, PUT, DELETE, STORE-запросов. Межсайтовый скриптинг XSS (англ. Cross-Site Scripting). Выводить текст сохраненной не вами на страницу так как его вводили.Тут есть нюансы. Если пользователь сохраняет текст (К примеру оставляет комментарий, или делает поиск по сайту) у вас в базе или еще где нибудь, то надо учесть что если нужен только текст тогда до сохранения очистить его от нежелательных тeгов(Для PHP strip_tags — Удаляет HTML и PHP-теги из строки). Если все таки нужно пропускать теги то сделать какие нибудь предварительные валидации.Или вводить их маркируя по принципу stackoverflow textarea.Мы же публикуя вопрос или ответ не можем же вводить любой тег.Просто забыл как называется такие типы маркировки текста :) Всегда тщательно проверяйте файлы которые загружаются на сервер через форму или каким нибудь способом.Проверяйте их расширения и содержимое.Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.Чтобы удостовериться, что это действительно изображение не используйте getimagesize() для проверки того, что файл является файлом с изображением. Для этих целей используйте расширение Fileinfo. Стоит добавить, что желательно сделать приведение файла к конкретному формату, например png. При приведении метаданные картинки потеряются, обеспечив практически гарантируемую безопастность.Наличие в загрузке файлов с расширением типа .php нужно проверять вообще в начале работы сайта, и если они есть сразу же их отбрасывать.
На уровне .htaccess
Ограничивать точки входа на сайте
Например в фреймворках в основном доступ идет через index.php.Или других вами известных файлах (admin.php,back.php, ...). Всегда можно отследить обращение к другому файлу, и всегда можно логировать информацию об обращениях к подозрительному файлу в отдельном журнале. проверьте .htaccess файлы на подозрительные изменения.auto_append_file и auto_prepend_file включают другие PHP файлы в начале или в конце всех PHP скриптов, злоумышленники могут использовать их для включения своего кода. find . -type f -name '\.htaccess' | xargs grep -i auto_prepend_file; Следующая команда ищет во всех подкаталогах файлы .htacсess, которые содержат 'http'. Результатом поиска будет список всех правил перенаправлений, в которых могут быть и вредоносные правила find . -type f -name '\.htaccess' | xargs grep -i http; . Во все каталоги, доступные для записи добавляем файл .htaccess со следующим содержимым:
php_flag engine 0
AddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp
Этим самым мы отключаем PHP в данном каталоге и заставляем все скрипты отображаться как HTML. Это можно сделать просто на всякий случай. Лишним уж точно не будет.
Или запрет на исполнение:
Order Allow,Deny Deny from all
На уровне баз данных,частностью MySQL:
Всегда пользуйтесь Подготовленными запросами и хранимыми процедурами: Большинство баз данных поддерживают концепцию подготовленных запросов. Что это такое? Это можно описать, как некий вид скомпилированного шаблона SQL запроса, который будет запускаться приложением и настраиваться с помощью входных параметров. У подготовленных запросов есть два главных преимущества:
Запрос необходимо однажды подготовить и затем его можно запускать столько раз, сколько нужно, причем как с теми же, так и с отличающимися параметрами. Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL инъекций случиться не может (однако, если другие части текста запроса записаны с неэкранированными символами, SQL-инъекции все же возможны; здесь речь идет именно о параметрах). Защищайтесь от SQL-инъекции
Прямое внедрение вредоносных инструкций в SQL-запросы - это методика, в которой взломщик создает или изменяет текущие SQL-запросы для отображения скрытых данных, их изменения или даже выполнения опасных команд операционной системы на сервере базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из пользовательского ввода и статических параметров.
На уровне системы Linux ...
Лучше этих сервисов, которые реально защищают от DDOS, я пока не знаю.Пользуюсь ими.Пока что отбивают :).Это Cloudflare ,и Incapsula
Как устроить ловушку для хакера (Honeypot - горшочек с медом):
Не занимайтесь этим если у вас нет достаточных знаний и квалификации, хакер может победить вас в вашей же ловушке.
Honeypot (горшочек с медом) давно широко используется в мире компьютерной безопасности.Это ресурс, задача которого отдаться хакеру, цель которого принять тест, атаку и быть взломанным.
Это может быть эмулятор другой системы или приложения, некая "темница с засадой", или просто стандартная система. Как бы вы не построили свой горшочек, главная его задача — подвергнутся нападению и рассказать вам в подробностях об этом.
Quick and Simple PHP Honey Pot Spam Prevention Simple PHP HoneyPot Tutorial Изучить инструменты, тактику и мотивы, связанные с компьютерными и сетевыми атаками, и поделиться извлеченными уроками.
Естественно все в этом посте перечислить невозможно.Но если попытаться реализовать все что в этом посте перечислено,то можно научиться защищаться и не хило.По каждому из пунктов можно всегда задать вопрос или поискать больше информации для более детальной и правильной ее реализации.
Полезные материалы :
Веб-сервисы для проверки сайтов на вирусы https://habrahabr.ru/post/303956/ Методы борьбы с DDoS-атаками https://habrahabr.ru/post/129181/ 5 советов по борьбе с DDOS-атаками http://www.securitylab.ru/analytics/442099.php Устоять любой ценой: методы борьбы с DoS/DDoS-атаками https://xakep.ru/2009/10/14/49752/ 5 программ для анализа безопасности Вашего сайта https://seo-zona.ru/5-programm-dlya-analiza-bezopasnosti-vashego-sajta-2015-03-31.html Как понять что ваш сайт был взломан https://www.siteguarding.com/ru/kak-poniat-chto-vash-sait-byl-vzloman
Бесплатный онлайн-сканеры вирусов:
Веб-сканер QUTTERA https://quttera.com/ Веб-сканер ReScan.pro https://rescan.pro/ VirusTotal https://www.virustotal.com/ru/ Веб-сканер Sucuri https://sitecheck.sucuri.net/ Онлайн—сканеры Dr.Web https://vms.drweb.ru/online/
Вооружайтесь знаниями. Будьте бдительней.
Удачи :)

воскресенье, 30 сентября 2018 г.

Как устроить ловушку для хакера, или достойно отбивать атаки?

Ребята выручайте. Меня взломали и в наглую соединились со мной, требуя денег. Я новичок в этом деле и думаю, что пока научусь, то офис скорее снимет меня с работы.
Недавно сайт стал зависать, похоже было на DDOS атаку. Забанил его по IP, но бесполезно. Я устал бегать за IP и банить их, да и в принципе это не выход. Просто когда с хакером переписывался, он сделал ряд проколов, сказав, что может сломать даже мою базу данных. Я когда проверял базу во время перегрузок, то на нее никаких нагрузок не было, в основном на сервер. Меняю всякий раз все возможные пароли, но хакер беспрепятственно обходит их.
И так, шаря, да выискивая слабые места, наткнулся на то, что мой сервер выдает страницы не только по index.php, но и по abc.php, xyz.php. Не знаю, блин, но носом чую, что гад припрятал какой-то файл и обращается к нему. Где и идут тормоза, заполняя канал на 100%. Базу удалить, в принципе, можно будет изнутри этого файла (DELTE FROM tbl_name).
Как можно найти этот файл, или как можно понять какой-то необычный вход на сервер? У меня Symfony 1.4 PHP фреймворк. Сайт 5 летней давности. Писать его заново? (не вариант, по крайней мере не сейчас). Что я пропустил на уровне хранения лишнего файла? Или не в ту сторону копаю?
Я слышал от друзей что в 90 % за этим стоят конкуренты. И в обратку хакнув его, чаще всего ддос прекращается. Но мысль навредить кому-то из за своей слабости чего-то не вдохновляет.
Попросил хакера дать время, чтоб якобы уболтать начальство расскошелиться.


Ответ

В принципе не важно вас взломали,или пытаются взломать,ведь рано или поздно мы сталкнёмся с этой угрозой. Всe действия описанные ниже помогут узнать о ваших слабых и уязвимых местах, помогут исправить допущенные ошибки, помогут вам грамотно защищаться и в дальнейшем эффективно бороться с этим злом. Научимся методике и технологиям устраивании ловушек для злоумышленников (Honeypot - горшочек с медом).
Приведу действия первой необходимости:
Если вас уже взломали:
Меняем логины и пароли серверов (Linux, MySQL, .....). Убеждаемся что у нас как минимум две группы пользователей с разными привилегиями.Допустим web и root, где web эта привилегия стоит для всех пользователей с ограниченными возможностями(Запрет на закачку файлов кроме image type). Как правильно дать привилегии ? Читаем Как Повысить безопасность и удобство использования Вашего сервера и заложить прочную основу для последующих действий. Если GIT не показывает необыкновенные изменения,то может быть стоит заглянуть в те директории которые вне него.Чаще всего это те директории куда загружаются изображения или иные файлы которые позволяем пользователям загружать. find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color Эта команда найдет php файлы содержащие eval(str_rot13(base64_decode( (Также можно искать и в базе данных SELCT col_nam FROM tbl_name WHERE col_name LIKE '%eval(str_rot13(base64_decode(%'). Синтаксис grep очень прост и вы можете изменить его под свои нужды.
На уровне PHP:
**Ограничивать использование опасных php функций в php.ini ** (disable_functions = "show_source, system, shell_exec, exec, eval" ).Можно закрыть mail() функцию.и зафиксировать обращение к SMTP через сокетное соединение на 25 порт. Тут обращу внимание на функцию eval. Если каким то образом в вашем коде припрятан PHP код то его исполнение через eval не произойдет.Этот список можно дополнять или убавлять по необходимости.Все отключили любые PHP скрипты которые были написаны надеюсь не нами. Межсайтовая подделка запроса (CSRF (англ. Сross Site Request Forgery )): Много популярных фреймворков имеют полноценную защиту от него в том числе и ваш.Распространённым способом защиты является механизм, когда с каждой сессией пользователя ассоциируется дополнительный секретный ключ,и при отправки запроса в месте с параметрами и отправляется сгенерированный токен.А потом сравниваются сгенерированный токен и токен пришедший с запросом,если совпадают то этот запрос неподделанный. Эффективен для выполнения POST, PUT, DELETE, STORE-запросов. Межсайтовый скриптинг XSS (англ. Cross-Site Scripting). Выводить текст сохраненной не вами на страницу так как его вводили.Тут есть нюансы. Если пользователь сохраняет текст (К примеру оставляет комментарий, или делает поиск по сайту) у вас в базе или еще где нибудь, то надо учесть что если нужен только текст тогда до сохранения очистить его от нежелательных тeгов(Для PHP strip_tags — Удаляет HTML и PHP-теги из строки). Если все таки нужно пропускать теги то сделать какие нибудь предварительные валидации.Или вводить их маркируя по принципу stackoverflow textarea.Мы же публикуя вопрос или ответ не можем же вводить любой тег.Просто забыл как называется такие типы маркировки текста :) Всегда тщательно проверяйте файлы которые загружаются на сервер через форму или каким нибудь способом.Проверяйте их расширения и содержимое.Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.Чтобы удостовериться, что это действительно изображение не используйте getimagesize() для проверки того, что файл является файлом с изображением. Для этих целей используйте расширение Fileinfo. Стоит добавить, что желательно сделать приведение файла к конкретному формату, например png. При приведении метаданные картинки потеряются, обеспечив практически гарантируемую безопастность.Наличие в загрузке файлов с расширением типа .php нужно проверять вообще в начале работы сайта, и если они есть сразу же их отбрасывать.
На уровне .htaccess
Ограничивать точки входа на сайте
Например в фреймворках в основном доступ идет через index.php.Или других вами известных файлах (admin.php,back.php, ...). Всегда можно отследить обращение к другому файлу, и всегда можно логировать информацию об обращениях к подозрительному файлу в отдельном журнале. проверьте .htaccess файлы на подозрительные изменения.auto_append_file и auto_prepend_file включают другие PHP файлы в начале или в конце всех PHP скриптов, злоумышленники могут использовать их для включения своего кода. find . -type f -name '\.htaccess' | xargs grep -i auto_prepend_file; Следующая команда ищет во всех подкаталогах файлы .htacсess, которые содержат 'http'. Результатом поиска будет список всех правил перенаправлений, в которых могут быть и вредоносные правила find . -type f -name '\.htaccess' | xargs grep -i http; . Во все каталоги, доступные для записи добавляем файл .htaccess со следующим содержимым:
php_flag engine 0
AddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp
Этим самым мы отключаем PHP в данном каталоге и заставляем все скрипты отображаться как HTML. Это можно сделать просто на всякий случай. Лишним уж точно не будет.
Или запрет на исполнение:
Order Allow,Deny Deny from all
На уровне баз данных,частностью MySQL:
Всегда пользуйтесь Подготовленными запросами и хранимыми процедурами: Большинство баз данных поддерживают концепцию подготовленных запросов. Что это такое? Это можно описать, как некий вид скомпилированного шаблона SQL запроса, который будет запускаться приложением и настраиваться с помощью входных параметров. У подготовленных запросов есть два главных преимущества:
Запрос необходимо однажды подготовить и затем его можно запускать столько раз, сколько нужно, причем как с теми же, так и с отличающимися параметрами. Параметры подготовленного запроса не требуется экранировать кавычками; драйвер это делает автоматически. Если в приложении используются исключительно подготовленные запросы, разработчик может быть уверен, что никаких SQL инъекций случиться не может (однако, если другие части текста запроса записаны с неэкранированными символами, SQL-инъекции все же возможны; здесь речь идет именно о параметрах). Защищайтесь от SQL-инъекции
Прямое внедрение вредоносных инструкций в SQL-запросы - это методика, в которой взломщик создает или изменяет текущие SQL-запросы для отображения скрытых данных, их изменения или даже выполнения опасных команд операционной системы на сервере базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из пользовательского ввода и статических параметров.
На уровне системы Linux ...
Лучше этих сервисов, которые реально защищают от DDOS, я пока не знаю.Пользуюсь ими.Пока что отбивают :).Это Cloudflare ,и Incapsula
Как устроить ловушку для хакера (Honeypot - горшочек с медом):
Не занимайтесь этим если у вас нет достаточных знаний и квалификации, хакер может победить вас в вашей же ловушке.
Honeypot (горшочек с медом) давно широко используется в мире компьютерной безопасности.Это ресурс, задача которого отдаться хакеру, цель которого принять тест, атаку и быть взломанным.
Это может быть эмулятор другой системы или приложения, некая "темница с засадой", или просто стандартная система. Как бы вы не построили свой горшочек, главная его задача — подвергнутся нападению и рассказать вам в подробностях об этом.
Quick and Simple PHP Honey Pot Spam Prevention Simple PHP HoneyPot Tutorial Изучить инструменты, тактику и мотивы, связанные с компьютерными и сетевыми атаками, и поделиться извлеченными уроками.
Естественно все в этом посте перечислить невозможно.Но если попытаться реализовать все что в этом посте перечислено,то можно научиться защищаться и не хило.По каждому из пунктов можно всегда задать вопрос или поискать больше информации для более детальной и правильной ее реализации.
Полезные материалы :
Веб-сервисы для проверки сайтов на вирусы https://habrahabr.ru/post/303956/ Методы борьбы с DDoS-атаками https://habrahabr.ru/post/129181/ 5 советов по борьбе с DDOS-атаками http://www.securitylab.ru/analytics/442099.php Устоять любой ценой: методы борьбы с DoS/DDoS-атаками https://xakep.ru/2009/10/14/49752/ 5 программ для анализа безопасности Вашего сайта https://seo-zona.ru/5-programm-dlya-analiza-bezopasnosti-vashego-sajta-2015-03-31.html Как понять что ваш сайт был взломан https://www.siteguarding.com/ru/kak-poniat-chto-vash-sait-byl-vzloman
Бесплатный онлайн-сканеры вирусов:
Веб-сканер QUTTERA https://quttera.com/ Веб-сканер ReScan.pro https://rescan.pro/ VirusTotal https://www.virustotal.com/ru/ Веб-сканер Sucuri https://sitecheck.sucuri.net/ Онлайн—сканеры Dr.Web https://vms.drweb.ru/online/
Вооружайтесь знаниями. Будьте бдительней.
Удачи :)