• Java. Сокеты. Как заставить сервер постоянно слушать до нажатия кнопки?

    Vamp
    @Vamp
    Нужно тело try блока, где открывается серверный сокет, обернуть в бесконечный цикл. Чтобы сервер не завершался после обработки первого клиента.
    Ответ написан
    5 комментариев
  • Как получить последний использованный прокси в Guzzle?

    Vamp
    @Vamp
    В guzzle есть другой способ передачи заданий - через promise.
    $requests = function () use ($data, $client) {
        foreach ($data as $item) {
            yield function () use ($client, $item) {
                return $client->sendAsync($item['request'])
                    ->then(function (Response $response) use ($item) {
                        echo $item['proxy'] . ' -> ' . $response->getStatusCode() . PHP_EOL;
                    });
            };
        }
    };
    Ответ написан
    1 комментарий
  • В чем практический смысл импорта функций из стандартной библиотеки?

    Vamp
    @Vamp
    Практический смысл видится мне только один - избежание проблем в случае появления в будущем в неймспейсе Foo\Bar функции, совпадающей по имени со стандартной.

    Но вероятнее всего это просто принятый в проекте стиль написания кода.
    Ответ написан
  • Безопасен ли удаленный доступ?

    Vamp
    @Vamp
    В вашем случае небезопасно. У Cisco AnyConnect есть функция, позволяющая работодателю загрузить на ваш компьютер и выполнить с правами администратора любой бинарник.

    Две ос на двух дисках - это хороший вариант, но только при условии, что домашний диск вы будете физически отключать от компьютера каждый раз перед загрузкой в рабочую ОС.

    Вариант получше - установить рабочую ОС в виртуальную машину hyper-v или virtualbox и работать в ней.
    Ответ написан
    4 комментария
  • Можно ли сделать динамическое добавление WebAPI?

    Vamp
    @Vamp
    1. Blue-green deployment. Запускаете два инстанса своего приложения. Один из них условно называется green, другой blue. Ставите перед ними nginx/haproxy и настраиваете проксирование всех запросов на green инстанс. Когда приходит время изменений, делаете их на blue инстансе, рестартите его и перенастраиваете проксирование всего трафика с green инстанса на blue. В следующий раз делаете то же самое, но с green инстансом.

    Этот вариант не требует ни строчки изменений в коде.

    2. В бесконечном цикле с паузой в 1 сек между итерациями читаете файлы с конфигурацией из нужной папки. Затем останавливаете сервисы, для которых не нашлось определения в конфиге, запускаете сервисы, для которых определение есть и перезапускате сервисы, у которых конфиг изменился. Это уже реализовано в spring boot externalized configuration, но ничто не мешает вам реализовать это руками.
    Ответ написан
    1 комментарий
  • Static члены не копируют своих данных даже в наследниках?

    Vamp
    @Vamp
    Static члены не наследуются, верно. Так как это бессмысленно.

    Просто я думал, зачем же нужен в enum valueOf(). Разобрался. Предположил, что метод хранит в себе строковое представление констант, а затем сравнивает вводные данные с ними.

    Метод valueOf() ничего не хранит и компилятор подставляет одинаковую реализацию valueOf() во всех enum'ах:

    public enum Hello {
        FIZZ, BUZZ;
    
        // Данный метод автоматически генерируется компилятором.
        // Для любого enum'а.
        public static Hello valueOf(String name) {
            return Enum.valueOf(Hello.class, name);
        }
    }


    А внутри Enum.valueOf обычный HashMap<String, Hello>, где ключом является имя константы, а значением соответствующий инстанс класса Hello. Не могу согласиться, что этот вариант плох с точки зрения оптимизации.

    Но так как я знаю, что константы в enum это анонимные классы

    Это не так. Константы - это конкретные инстансы вашего enum класса, а не инстансы анонимных наследников от него.

    Получается мне действительно прийдется перекрывать эти переменные повторным объявлением для разрыва связи с предком?

    Не очень понял суть вопроса. Чтобы разорвать связь с предком нужно просто удалить наследование от него.
    Ответ написан
    2 комментария
  • Как получить доступ к объекту js который выполняется в iframe?

    Vamp
    @Vamp
    document.getElementById('frameId').contentWindow.yourObject

    В данном примере получается доступ к объекту yourObject внутри iframe с id=frameId.

    Но это сработает только если сама страница и iframe в ней были загружены с одного домена.

    В остальных случаях доступ будет запрещен из-за same origin policy.
    Ответ написан
    1 комментарий
  • Что нужно вернуть при вызове сервиса методом OPTIONS?

    Vamp
    @Vamp
    Список поддерживаемых методов обычно передается через http заголовок Allow. Этот заголовок допускается возвращать в ответ на метод OPTIONS.
    HTTP/1.1 200 OK
    Allow: OPTIONS, GET, HEAD, POST
    Cache-Control: max-age=604800
    Date: Thu, 13 Oct 2016 11:45:00 GMT
    Expires: Thu, 20 Oct 2016 11:45:00 GMT
    Server: nginx
    Content-Length: 0


    По default планирую возвращать, что метод не поддерживается.

    Если вы планируете возвращать эту ошибку используя http код 405, то наличие заголовка Allow со списком поддерживаемых методов обязательно. Это требование RFC7231.
    Ответ написан
    Комментировать
  • PHP-DI и контроллеры. Как избежать повтора кода?

    Vamp
    @Vamp
    Если аргументы конструктора у контроллеров помечены type hint'ами, то контроллеры необязательно регистрировать в контейнере. Можно создавать их напрямую по имени класса:

    $controller3 = $container->get('project\Controllers\Controller3');

    Здесь используется фича autowiring, которая по умолчанию включена. PHP-DI смотрит при помощи рефлексии какие типы требует конструктор контроллера и подставляет соответствующие сервисы, зарегистрированные в контейнере.
    Ответ написан
    1 комментарий
  • Как защитить ПО от подделки ответа http?

    Vamp
    @Vamp
    Вашу программу взломали при помощи атаки mitm с подменой сертификатов. Это значит что программа не валидирует сертификат сервера (образно говоря, ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;), что позволяет злоумышленнику сгенерировать на ваш домен самоподписанный сертификат, перенаправить трафик на свой локальный сервер и программа будет доверять этому серверу как своему. Либо валидирует с использованием корневых сертификатов из trust store операционной системы. В этом случае злоумышленник просто добавит свой сгенерированный сертификат в trust store ОС и ваша программа будет доверять поддельным сертификатам злоумышленников.

    Решением этой проблемы является использование техники certificate pinning или public key pinning. То есть вам нужно зашить в программу корневой сертификат того CA, у которого вы приобретаете сертификаты (lets encrypt?) и валидировать ответы только с его использованием. Никакого доверия trust store ОС и никогда не игнорируйте ошибки валидации.
    Ответ написан
    Комментировать
  • Допускается ли возможность заражения машины сугубо открытием ссылки на сайт?

    Vamp
    @Vamp
    С лёгкостью заразиться не получится, потому что web стал слишком важной инфраструктурой, поэтому компании прилагают много усилий для его развития. В том числе в плане безопасности. Но софт пишут люди, а люди неспособны производить безошибочный код. Поэтому ошибки всегда будут, а значит и уязвимости, позволяющие обходить изолированную песочницу.

    Фактов полно в интернете. Например, этот:

    According to the screenshot shared by Agarwal, the PoC HTML file, and its associated JavaScript file, can be loaded in a Chromium-based browser to exploit the security flaw and launch the Windows calculator (calc.exe) app. But it's worth noting that the exploit needs to be chained with another flaw that can allow it to escape Chrome's sandbox protections.

    Или такой пример. Джеилбрейк iOS через уязвимость в браузере Safari.
    Ответ написан
    Комментировать
  • Как средствами PHP нарисовать дугу для SVG файла?

    Vamp
    @Vamp
    Проще всего нарисовать дугу через элемент path.

    $image = new SVG('100mm','100mm');
    $doc = $image->getDocument();
    $square = new SVGLine('0mm', '0mm', '55mm', '55mm'); // x0 y0 x1 y1
    $square->setStyle('stroke', '#FF0000'); //цвет
    $doc->addChild($square);
    
    $arc = new SVGPath('m 40,40 A 30,30,0,0,1,150,150');
    $arc->setStyle('stroke', '#FF0000');
    $doc->addChild($arc);
    
    header('Content-Type: image/svg+xml');
    echo $image;


    Нужно немного изучить формат path. Он не сложный.

    m 40,40 A 30,30,0,0,1,150,150

    m - это команда move. Устанавливает "кисть" в указанную позицию. Далее команда A - arc (дуга). Её формат несколько сложнее:

    30,30 - радиус дуги по осям x и y
    0 - угол поворота дуги вокруг оси x
    0 - должна ли дуга быть больше 180 градусов или нет
    1 - в какую сторону рисовать дугу - по часовой или против
    150,150 - координаты конца дуги
    Ответ написан
    2 комментария
  • Возможно ли выбрать российский сервер в CloudFlare?

    Vamp
    @Vamp
    Нет, вы не можете в CloudFlare выбирать местоположение. Даже сам CloudFlare не может.

    CloudFlare использует технологию anycast. В двух словах это когда один и тот же IP адрес анонсируется сразу несколькими географически разнесёнными дата центрами. И для посетителя из америки трафик будет приземляться на американский ДЦ, а для посетителя из россии на российский ДЦ даже если оба таких поселителя заходят на один и тот же IP адрес.

    Поисковики в курсе этой технологии, так как сами ею пользуются. Так что география сайта не определяется ими исключительно по IP адресу.
    Ответ написан
    2 комментария
  • Как собирать метрики с самого сервера через Prometheus?

    Vamp
    @Vamp
    Вам нужно установить на хост node_exporter (можно в докере). Он будет собирать метрики с хоста и экспортировать их для prometheus.
    Ответ написан
    Комментировать
  • Как проверить какая ошибка в $_FILES?

    Vamp
    @Vamp
    Согласно официальной документации, превышение post_max_size можно отследить только добавив get параметр к форме:
    <form action="edit.php?processed=1">

    if (!empty($_GET['processed']) && empty($_POST) && empty($_FILES)) {
        echo 'Ошибка! Вы загрузили слишком большой файл';
    }
    Ответ написан
  • Что будет за раскрытие факта уязвимости на гос-ресурсе?

    Vamp
    @Vamp
    Напишите обращение в Роскомнадзор. Персональные данные - это их вотчина.

    Мол, данный сайт раздает персональные данные направо и налево, прошу провести правовую оценку и принять меры.

    Не пишите про взлом или ещё что-то. Иначе это повод для ст. 272 УК РФ. Плохо, что вы угрожали публикацией в СМИ. Это тоже могут использовать против вас.
    Ответ написан
    Комментировать
  • Можно ли получать данные из ResultSet не удаляя их из ResultSet?

    Vamp
    @Vamp
    Можно "перемотать" ResultSet и повторно прочитать из него данные:
    try (ResultSet rs = statement.executeQuery(query)) {
        while (rs.next()) {
            System.out.println("User: " + rs.getString("login"));
        }
        rs.beforeFirst(); // <-- перематываем
        while (rs.next()) {
            System.out.println("Hello, " + rs.getString("login"));
        }
    }


    Но это не сработает, если драйвер создал ResultSet типа TYPE_FORWARD_ONLY или реализация ResultSet не поддерживает перемотку в принципе. В этом случае придётся прочитать весь результат полностью в промежуточное хранилище и дальше работать уже с ним:
    class User {
        private final String login;
        private final String name;
        private final String email;
    
        public User(ResultSet rs) throws SQLException {
            login = rs.getString("login");
            name = rs.getString("name");
            email = rs.getString("email");
        }
    
        public String getLogin() {
            return login;
        }
        public String getName() {
            return name;
        }
        public String getEmail() {
            return email;
        }
    }

    List<User> users = new ArrayList<>();
    try (ResultSet rs = statement.executeQuery(query)) {
        while (rs.next()) {
            users.add(new User(rs));
        }
    }
    for (User u : users) {
        System.out.println("Hello, " + u.getLogin());
    }

    Вариант с использованием отдельного класса для хранения результатов используется повсеместно и имеет своё собственное название - DTO (Data Transfer Object).
    Ответ написан
    Комментировать
  • Nginx, странно работает deny all. Что делать?

    Vamp
    @Vamp
    У обычного префиксного location приоритет ниже, чем у location с регулярным выражением.

    Повысьте приоритет запрещающего правила модификатором ^~:
    location ^~ /engine/ {
        deny all;
    }
    Ответ написан
    Комментировать
  • Почему поток не отрабатывает задуманного в Java?

    Vamp
    @Vamp
    Такой вывод получается из-за того, что тест считается завершенным сразу после выхода из метода runWithSleep, после которого программа завершается принудительно, несмотря на наличие всё ещё выполняющихся не daemon потоков.

    Чтобы увидеть полный вывод запустите код не в контексте junit или добавьте ожидание в код теста:

    exec.shutdown();
    exec.awaitTermination(100, TimeUnit.SECONDS);
    Ответ написан
    2 комментария