• Разработка игр под Android - с чего начать?

    coder1cv8
    @coder1cv8
    Инди-разработчик
    А никто не представляет, что там за движки-не движки и с чего начинать вообще.. Просто берете и начинаете, гуглите движки - выбираете, потом гуглите как создать проект в конкретном движке, потом гуглите как эту вашу платформу для "дудл джампа" нарисовать на экране, потом как заставить камеру двигаться и тд и тп. Короче, смысл в том, чтобы решать конкретные маленькие задачи, а не думать о правильном подходе. Надо изначально понимать, что первая игра неизбежно будет адом и ужасом в плане архитектуры, оптимальности кода и прочих "бэст прэктис". И вторая тоже, и третья.. А потом - ОП! и после n игр ты уже понимаешь чем тот движок отличается от этого, из каких "кубиков" должна состоять игра и как их заставить между собой взаимодействовать и жить своей жизнью.
    Ответ написан
    Комментировать
  • Как убрать повторяющиеся слэши в .htaccess?

    Два коммента выше про:

    RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
    и про
    RewriteCond %{THE_REQUEST} ([^\s]*)\/{2,}(\?[^\s]*)?

    Вы вообще сами проверяли как будет происходить редирект? А я отвечу, что станицы вида site.ru/page//// будут редиректиться сначала на site.ru/page/// потом на site.ru/page// потом только на site.ru/page/

    Потому как что (.*), что ([^\s]*) - жадные! Нужно указывать (.*?) и ([^\s]*?)

    Господа, проверяйте свой код прежде, чем рекомендовать кому то.
    Ответ написан
    Комментировать
  • Как пушить на github чтобы не вводить каждый раз логин и пароль?

    bukinion
    @bukinion
    Некороткий мануал по SSH + GitHub & BitBucket (на Win, почти тоже и на Lin)

    Вначале надо найти ключи
    $ ls -al ~/.ssh
    # Спискок файлов в директории .ssh, если они есть
    # id_rsa.pub # Нам интересны эти два брата, точнее этот публичный код (паб)
    # id_rsa # Это для сверки с пабом


    Если их нет, то будем генерить, после чего ласково попросят пароль, он должен быть сложным, в конечном итоге вводится он будет только один раз при старте сессии.
    $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    # Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]
    # Enter passphrase (empty for no passphrase):
    # Enter same passphrase again:


    Кстати, пароль можно и поменять:
    $ ssh-keygen -p # Введете старый, а потом новый.

    Консоль выведет следующее:
    # Your identification has been saved in /Users/you/.ssh/id_rsa.
    # Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
    # The key fingerprint is:
    # 01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db your_email@example.com


    Теперь надо добавить ваши ключи в ssh-агент
    Удостоверьтесь в том, что он у вас есть — запустите
    $ ssh-agent -s

    Должен быть следующий однострочный (!) вывод, номер pid будет другим, все остальное от лукавого:
    Agent pid 59566

    Если нет, то скорее всего в терминале другая оболочка, тогда:
    $ eval $(ssh-agent -s)
    Agent pid 59566


    Вот теперь можно добавить ключи в ssh-агент
    $ ssh-add ~/.ssh/id_rsa

    Далее, добавим ключи в VCS-сервисы github и bitbucket, для этого скопируйте содержимое id_rsa.pub, и вставьте в настройках своего аккаунта на VCS (например, "SSH and GPG keys" для Github). Активируем ключи.

    для github:
    $ ssh -T git@github.com

    чуть длинней, для bitbucket, вначале надо создать файл-конфиг, ~/.ssh/config, куда добавить следующие строки:
    Host bitbucket.org
    IdentityFile ~/.ssh/id_rsa # Тут приватный ключ!


    После чего запустить следующую команду:
    $ ssh -T git@bitbucket.org

    В каждом случае, если все пройдет успешно, то вы получите следующие сообщения:
    Hi #{username}! You've successfully authenticated, but GitHub does not provide shell access.


    или
    conq: logged in as tutorials.
    You can use git or hg to connect to Bitbucket. Shell access is disabled.


    К слову, что Github, что Bitbucket выдали мне в этот раз такое:
    Thу authenticity of host 'github.com (192.30.253.113)' can't be established.
    RSA key fingerprint is 12:12:12...12.
    Are you sure want to conecting (yes/no)?


    Ответил yes, консоль что-то ответила и все работает.

    Если же вы используете алиасы для хостов, то и активация должна быть через алиас:

    $ ssh -T git@alias


    Если работаете с Sourcetree (рекомендую для винды), то есть такой момент, что программа не принимает стандартный формат этих ключей и что бы работать с программой через ssh придется из полученного ключа (приватный) сгенерировать их в другом формате понятном putty. Для этого используется программа puttygen. Которая входит в поставку Sourcetree.


    Занудно, но уже финал близок, далее нам нужно настроить ~/.bashrc, которого на винде нет, именно он будет содержать инициализационные настройки для консоли и запускать ssh-агент, который будет включать ваши ключи, запоминать сессию:
    # Note: ~/.ssh/environment should not be used, as it
    #       already has a different purpose in SSH.
    
    env=~/.ssh/agent.env
    
    # Note: Don't bother checking SSH_AGENT_PID. It's not used
    #       by SSH itself, and it might even be incorrect
    #       (for example, when using agent-forwarding over SSH).
    
    agent_is_running() {
        if [ "$SSH_AUTH_SOCK" ]; then
            # ssh-add returns:
            #   0 = agent running, has keys
            #   1 = agent running, no keys
            #   2 = agent not running
            ssh-add -l >/dev/null 2>&1 || [ $? -eq 1 ]
        else
            false
        fi
    }
    
    agent_has_keys() {
        ssh-add -l >/dev/null 2>&1
    }
    
    agent_load_env() {
        . "$env" >/dev/null
    }
    
    agent_start() {
        (umask 077; ssh-agent >"$env")
        . "$env" >/dev/null
    }
    
    if ! agent_is_running; then
        agent_load_env
    fi
    
    # if your keys are not stored in ~/.ssh/id_rsa or ~/.ssh/id_dsa, you'll need
    # to paste the proper path after ssh-add
    if ! agent_is_running; then
        agent_start
        ssh-add
    elif ! agent_has_keys; then
        ssh-add
    fi
    
    unset env


    И снова не финал, скорее всего так как вы не пользовались SSH, то ваши уже существующие локальные репо будут работать по http/https, поэтому надо сменить адреса. Адреса удаленных репозиториев проверяются командой $ git remote -v. Для смены адресов git есть специальная команда: $ set-url, ввести следующее:
    $ git remote set-url origin git@github.com:USERNAME/OTHERREPOSITORY.git


    Вернуть все на Родину можно аналогично
    Ответ написан
    1 комментарий
  • Раcширение для управления LocalStorage?

    А чем встроенная dev консоль (F12/Resources/Local Storage) не устраивает?
    Ответ написан
    5 комментариев
  • По какой причине не работают :after/:before у select?

    andykov
    @andykov
    Shit happens
    Потому что у select как и у input элементов нет содержимого, а эти псевдоэлементы добавляются именно к нему.
    Ответ написан
    7 комментариев
  • Чем webpack лучше gulp/grunt?

    Webpack - это система сборки с массой возможностей. В частности, он анализирует JS-код (а также CSS или другой, через лоадеры), это даёт ему superpowers.

    Gulp/grunt - это общая система для организации задач, которая сама по себе сборку не поддерживает, но её можно на ней написать, с помощью плагинов. При этом анализа кода, скорее всего, не будет, а значит ряд продвинутых фич отпадут.

    То есть, это две разные вещи. В качестве одной из задач на gulp/grunt вполне может быть сборка webpack, так обычно и делают.

    Простую сборку вполне можно написать и на gulp/grunt напрямую. А если посложнее или просто хочется иметь задел "на будущее", то можно воспользоваться специальным инструментом (Webpack).

    P.S. У меня когда-то были и gulp task'и сборщики и browserify, но уже давно их место плотненько занял Webpack.
    Ответ написан
    18 комментариев
  • Как подключить json файл в vue.js правильно?

    owl1n
    @owl1n
    fullstack developer
    Так как вы используете подход single view component, то советую вам оформить ваш JSON файл как JSONP, и подключить через script :)
    Если бы вы использовали, допустим, webpack, то можно было бы в теле вашего app.js написать
    const userData = require(‘axample.json’)
    Ответ написан
    Комментировать
  • Кто использует такой подход в написании CSS?

    nikichv
    @nikichv
    Frontend dev. Current stack: Next.js/RTK/Saga
    Обычный хороший подход, даже правильный я бы сказал. Сам давно использую. И это действительно удобно, что можно в одном месте просмотреть все стили элемента по всем брейкпоинтам. В чем вопрос только непонятно. :)
    Особенно удобно в сочетании с бутстрапом:
    .logo {
      width: 198px;
      height: 122px;
    
      background-repeat: no-repeat;
      background-size: cover;
      background-position: center;
    
      @include media-breakpoint-down(sm) {
        display: none;
      }
    }
    Ответ написан
    4 комментария
  • Кто использует такой подход в написании CSS?

    IonDen
    @IonDen
    JavaScript developer. IonDen.com
    Совершенно нормальный подход. Пишу так же, пример:
    .footer {
        position: relative;
        background-color: @dark-grey-blue;
        color: @white;
        font-size: 12px;
        padding: 20px;
        box-sizing: border-box;
    
        @media @desktop {
            height: 200px;
            padding: 0;
        }
    
        &__text {
            display: block;
            text-align: center;
    
            @media @desktop {
                position: absolute;
                top: 75px;
                left: 15px;
                width: 250px;
                text-align: left;
            }
        }
    }
    Ответ написан
    Комментировать
  • Какой слайдер-карусель вы используете с Vue.js?

    @tvelforce
    Легкий и простой
    https://github.com/Featurum/vue-slider
    Ответ написан
    Комментировать
  • Как сделать AJAX запрос безопасным?

    @cluberr
    Защита: используем nonce и проверяем права

    Нет острой необходимости проверять AJAX запрос, если он потенциально не опасный. Например, когда он просто получает какие-то данные. Но когда запрос удаляет или обновляет данные, то его просто необходимо дополнительно защитить с помощью nonce кода и проверкой прав доступа.

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

    Существует два вида защиты, которые нужно использовать в AJAX запросах в большинстве случаев.

    1. Код nonce (случайный код)

    Nonce - это уникальная строка, которая создается и используется один раз - одноразовое число. Nonce проверка используется, когда нужно убедится, что запрос был послан с указанного «места».

    В WordPress есть функции wp_create_nonce() и check_ajax_referer() - это базовые функции для создания и последующей проверки nonce кода. С их помощью мы и будем создавать защиту nonce для AJAX запросов.

    Для начала создадим nonce код:

    add_action( 'wp_enqueue_scripts', 'myajax_data', 99 );
    function myajax_data(){
    
    	wp_localize_script('twentyfifteen-script', 'myajax', 
    		array(
    			'url' => admin_url('admin-ajax.php'),
    			'nonce' => wp_create_nonce('myajax-nonce')
    		)
    	);  
    
    }

    twentyfifteen-script это название основного скрипта темы (см. выше), который подключается на сайте с помощью wp_enqueue_script().

    Затем, в AJAX запросе добавим переменную с кодом nonce:

    var ajaxdata = {
    	action     : 'myajax-submit',
    	nonce_code : myajax.nonce
    };
    jQuery.post( myajax.url, ajaxdata, function( response ) {
    	alert( response );
    });

    Теперь, в обработке заброса необходимо проверить nonce код:

    add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
    add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
    function myajax_submit(){
    	// проверяем nonce код, если проверка не пройдена прерываем обработку
    	check_ajax_referer( 'myajax-nonce', 'nonce_code' );
    	// или так
    	if( ! wp_verify_nonce( $_POST['nonce_code'], 'myajax-nonce' ) ) die( 'Stop!');
    
    	// обрабатываем данные и возвращаем
    	echo 'Возвращаемые данные';
    
    	// не забываем завершать PHP
    	wp_die();
    }

    check_ajax_referer()работает на основе функции wp_verify_nonce() и по сути является её оберткой для AJAX запросов.
    Обратите внимание, что в данном случае Nonce код создается в HTML коде. А это значит, если у вас установлен плагин страничного кэширования, то этот код может и наверняка будет устаревать к моменту очередного AJAX запроса.
    2. Проверка прав доступа

    Тут AJAX запросы будут срабатывать только для пользователей с правом author. Для всех остальных включая неавторизованных пользователей, AJAX запрос вернет ошибку.

    Особенность тут в том, что не авторизованные пользователи тоже должны видеть сообщение об ошибке при AJAX запросе. Для этого нужно обрабатывать запрос для них возвратом ошибки:

    add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
    add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
    function myajax_submit(){
    	// проверяем nonce код, если проверка не пройдена прерываем обработку
    	check_ajax_referer( 'myajax-nonce', 'nonce_code' );
    
    	// текущий пользователь имеет права автора или выше
    	if( ! current_user_can('publish_posts') )
    		die('Этот запрос доступен пользователям с правом автора или выше.')
    
    	// Делаем что нужно и выводим данные на экран, чтобы вернуть их скрипту
    
    	// Не забываем выходить
    	wp_die();
    }
    Ответ написан
    2 комментария
  • Не работают транзакции при миграциях в Yii2. ??

    @BorisKorobkov Куратор тега MySQL
    Web developer
    DDL (create, alter, drop) откатить нельзя. Это не Yii и даже не PHP, а MySQL.
    Ответ написан
    1 комментарий
  • Как в Bootstrap создать многоуровневое меню или список?

    webinar
    @webinar Куратор тега Yii
    Учим yii: https://youtu.be/-WRMlGHLgRg
    А чем Вас yii\widgets\Menu не устраивает?
    www.yiiframework.com/doc-2.0/yii-widgets-menu.html
    Да и тот же nav не ограничен одним уровнем.
    Ответ написан
    Комментировать
  • Авторизация через соц. сети в концепции SPA?

    @vetsmen Автор вопроса
    Кому интересно решение данной задачи: все предельно просто.
    Сначала создаем pop-up окно, авторизовываемся в нем и редиректимся на нашу страницу прослойку, там мы имеем уже наш jwt токен (или любой другой) и через window.opener мы можем вызвать любой метод в родительском окне. К примеру: window.opener.setToken('{token}'), перед этим определив функцию в родительском окне:
    window.setToken = function(token){ /* записываем наш токен */}
    Ответ написан
    Комментировать
  • Какие прорехи в безопасности могут быть в конфигурации nginx?

    1. Постоянный редирект с / на index.php

    location = / {
            rewrite ^ $scheme://$host/index.php permanent;
        }
    
        location / {
            deny all;
            return 404;
        }
        location ~* ^/index\.php$ {
            try_files $uri $uri/ =404;
            fastcgi_index index.php;
            fastcgi_pass php5-fpm-sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include /etc/nginx/fastcgi_params;
        }



    Очень странная логика, особенно использование $host и некорректное использование try_files. Про try_files почитайте тут.

    $host
    в порядке приоритета: имя хоста из строки запроса, или имя хоста из поля “Host” заголовка запроса, или имя сервера, соответствующего запросу


    Если у вас не определен default_server и server_name site.ru; стоит первым в списке, то к вам будут прилетать все запросы с любым полем Host, в том числе пустым, что является очень опасной практикой.
    Лучше использовать переменную $server_name, но все равно, если вам нужно обращения по любым url обрабатывать только через index.php, то правильно это делается так:

    /NONEXISTENTFILE меняете на заранее фейковый файл который не может существовать, например /d7sdhsdhsdf8sfhgsfd8fh438dfjh

    ...
            error_page 404 = @cms;
    
            location / {
                try_files /NONEXISTENTFILE @cms;
            }
    
            location @cms {
                    fastcgi_pass      unix:/var/lib/php5-fpm/xxxxx.sock;
                    fastcgi_index    index.php;
                    fastcgi_param   SCRIPT_FILENAME $document_root/index.php;
                    fastcgi_param   SCRIPT_NAME /index.php;
                    include             /etc/nginx/fastcgi_params;
            }
    ...


    2. Запрещаем любую статику кроме gif|jpg|png|js|css|ttf|woff|ico
    location ~* \.(gif|jpg|png|js|css|ttf|woff|ico)$ {
            try_files $uri =404;
            expires 30d;
        }



    Логичнее и правильнее будет сделать так:

    try_files $uri =404; нам не понадобится, т.к. у нас есть error_page 404 = @cms; который в случае отсутствия картинки перенаправит запрос в @cms

    ...
            error_page 404 = @cms;
    
            location ~* ^.+\.(gif|jpg|png|js|css|ttf|woff|ico)$ {
                    expires 30d;
                    access_log off;
                    log_not_found off;
            }
    
            location / {
                try_files /NONEXISTENTFILE @cms;
            }
    ...


    По поводу json.php и в принципе ограничения доступа, правильнее делать это через map или geo, например так:

    http {
    ....
            geo $my_client_ip $denied {
                    default 1;
                    127.0.0.1 0;
                    XX.XX.XX.XX 0; # <- IP1 с которого можно заходить
                    YY.YY.YY.YY 0;    # <- IP2 с которого можно заходить
            }
    
    server {
            listen       443 ssl;
            server_name  site.ru;
            root         /var/www/html/;
    ...
            set $my_client_ip $remote_addr;
            if ($http_x_forwarded_client_ip ~ "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") {
                    set $my_client_ip $http_x_forwarded_client_ip;
            }
    
            error_page 403 = @deny;
    
            location @deny {
                    root /var/www/deny;
                    rewrite ^(.*)$ /index.html break;
            }
    
            location ~* ^/json\.php$ {
                    if ($denied) {
                            return 403;
                    }
                    try_files /NONEXISTENTFILE @json;
            }
    
            location @json {
                    try_files       $uri = 404;
                    fastcgi_pass    unix:/var/lib/php5-fpm/xxxxx.sock;
                    fastcgi_index   index.php;
                    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include         /etc/nginx/fastcgi_params;
            }
    
    }
    }


    4. Разрешаем доступ к /admin только с 1-го IP, для /admin/phpmyadmin


    Не делайте так! Организуйте для phpMyAdmin отдельный поддомен с отдельным виртуальным сервером и отдельной обработкой php5-fpm через отдельный сокет.
    Никогда не храните "левые" (вспомогательные) утилиты в общем каталоге web-приложения, это плохая практика. К примеру: Если в phpMyAdmin будет найдена критическая уязвимость, то даже в случае ограничения доступа к нему с определенного IP существует вероятность, что она может быть проэксплуатирована и тогда через неё поломают ваше web-приложение - оно вам нужно?

    По поводу location ~* /admin/ аналогично как для json.php.

    Ну и все рекомендации выше от Кирилл Несмеянов относительно hsts, ssl, ciphers, dh, ocsp stapling поддерживаю.
    Ответ написан
    4 комментария
  • Какие прорехи в безопасности могут быть в конфигурации nginx?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    1) Отсутствует hsts заголовок
    2) Не указаны SSL протоколы, стоит явно прописать TLS, т.к. остальные потенциально не безопасные
    3) Отсутствует перечисление ciphers (потенциально допустимы слабые и небезопасные алгоритмы)
    4) Отсутствует ключик диффи
    5) Используется потенциально небезопасная и устаревшая версия PHP
    6) Включена (не отключена) передача заголовков сервера (т.е. информация о том, что используется nginx)
    7) Отсутствуют OCSP Stapling настройки (насколько я помню - могут возникнуть проблемы с отозванными сертификатами x.509)

    По поводу настройки самих урлов - хз. Самая лучшая защита и самая адекватная - это просто хранить в web-корне только то, что может быть доступно наружу, как делают все адекватные фреймы, например: https://github.com/laravel/laravel/tree/master/public
    Это значит, что в вашем случае их всего два должно быть - это index и json (второй просто прикрыт по айпишнику), остальные вариант ничего не гарантируют.

    Тоже самое и с phpmyadmin. Зачем он? Неужели workbench, phpstorm или ещё что с соединением сквозь ssh туннель по сертификату будет менее удобен или безопасен? Не верю.

    С админкой, соглашусь, но там, кажется, всё в пределах нормы. Только, кажется, имеет смысл перенастроить каким-нибудь таким (не обязательно прям так, ибо я не проверял как работает пример) образом:
    location ~ /admin/*.\.php$ {
        try_files $uri $uri/ /admin/index.php?$query_string =404;
        // ...
    }

    Т.е. чтобы любой запрос куда-либо отправлял на его index. Не?
    Ответ написан
    1 комментарий
  • Как защитить API сервиса платного контента?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    Шифруйте отдаваемый контент через RSA между сервером и приложением. (SSL/не SSL - это мы сейчас не рассматриваем!)

    1. Формируйте УНИКАЛЬНЫЙ! контент/трафик для каждого пользователя и расшифровывайте доставленный контент исключительно в памяти приложения, непосредственно перед моментом отображения на экране!

    2. Используйте платёжные данные при шифровании данных на сервере.
    3. Меняйте ключ при каждом запросе на основе номера пакета текущей сессии, времени, случайного числа и т.д.
    4. Отдавайте контент порциями с разным шифрованием - prefetch/segmentation.
    5. Обновляйте протокол внутреннего шифрования хотя бы раз в 1-2 месяца.

    Нет 100%-ой защиты на клиенте, которая не позволила бы сохранять контент.
    За то - можно это усложнить до нереальных трудозатрат.
    Ответ написан
    Комментировать
  • Как защитить API сервиса платного контента?

    Kwisatz
    @Kwisatz
    Больше web-приложений, хороших и разных
    Запомните пожалуйста: клиент в руках врага. Всегда. Исключений нет. Любая защита может быть только на сервере, на клиенте - только видимость.
    Ответ написан
    4 комментария
  • Как сделать адаптивное изображение в блоке?

    vollthegreat
    @vollthegreat
    Laravel back-end outsource
    попробовать тег < picture > под размеры экрана...
    Ответ написан
    Комментировать
  • Как сделать адаптивное изображение в блоке?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    1. Есть тег <picture> для показа разных изображений на разных экранах
    2. height: auto для пропорций
    3. позиционирование
    4. object-fit для правильной обрезки, аналогичной bg size.

    Про то, что картинки можно готовить заранее правильных пропорций лучше промолчу.

    При наличии этого всего не понятно зачем нужна манипуляция превращения картинок в фон. Разве что кто-то знает js лучше, чем css.
    Ответ написан
    3 комментария