Category: Web

23
Июл
2021

🕸 16 шагов к профессии: дорожная карта фронтенд-разработчика в 2021 году

Считается, будто порог входа во фронтенд-разработку невысок. Этот стереотип испортил репутацию профессии, приведя в нее немало готовых работать за еду новичков. Рассказываем, как не пополнить их ряды.

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

Обязанности фронтенд-разработчика

Список задач, которые решает Front-end developer, меняется в зависимости от специфики проекта и уровня подготовки разработчика. В него могут входить следующие позиции:

  • кросс-платформенная и адаптивная верстка сайтов;
  • работа со стеком Redux/React;
  • сопровождение и доработка проектов;
  • написание скриптов и создание реактивных компонентов;
  • поддержка проектов ES5;
  • развитие и поддержка архитектуры, основанной на виджетах и компонентах;
  • выполнение рефакторинга проектов;
  • разработка новых npm-модулей в существующих приложениях;
  • автоматизация тестирования и устранение багов, иногда с фрейморком JUnit;
  • разработка сайтов на Angular;
  • сопровождение и разработка сервисов, направленных на распознавание лиц и обработку видео;
  • разработка компонетов на Vue.
Развитие профессии привело к увеличению требований к начинающим фронтенд-разработчикам. На 2021 год Roadmap состоит из многих пунктов, разобраться с которыми поможет подборка на GitHub. Мы попробуем свести данные из разных источников воедино и на их основе составим свой план.

1. Изучите HTML, JavaScript и CSS


Веб-разработчикам никуда не деться от изучения трех «китов»: разметки (HTML), каскадной таблицы стилей (CSS) и языка программирования JavaScript. С этим помогут материалы на CodeAcademy и YouTube: HTML Full Course, CSS Tutorial и CSS Crash Course for Absolute Beginners, Object-oriented Programming in JavaScript.

2. Изучите несколько фреймворков

Для работы потребуется использовать один/несколько фреймворков: ReactJS, AngularJS, VueJS, Bootstrap. Разобраться с React JS поможет ролик freeCodeCamp на YouTube, там же можно найти курс по VeuJS.

3. Освойте работу с генераторами статических сайтов

Примеры статических сайтов: визитки, лендинги, справочники, каталоги продукции. Упростить их создание помогут: Next (React-based), Nuxt (Vue-based), Gatsby (React-based), Gridsome (Vue-based).

4. Научитесь работать с JAMstack

Расшифровка акронима JAM: JavaScript, API and Markup. Архитектура JAMStack основана на клиентском JavaScript, повторно используемых API и предварительно созданной разметке. Что такое JAMStack и как с ним работать можно почитать здесь и на snipcard. Дополнительно в стеке используют CDN и Git.

5. Освойте Progressive web apps (PWA)

Знания PWA (англ. progressive web app или мобильное приложение в браузере) потребуются опытным разработчикам. Прогрессивные приложения направлены на надежность и быстроту работы с технологиями Push Notifications, Service Worker, Web App manifest, App shell, HTTPS.

6. Освойте GraphQL


Этот язык запросов и манипулирования данными для API (а также среда выполнения запросов) является основным для каждого фронтендера, который не хочет работать за еду. Обрабатывающий запросы сервер GraphQL находится между клиентом и источниками данных.

На платформе Apollo реализация GraphQL направлена на транспортировку данных из облачного хранилища к пользовательскому приложению, а поклонники фреймворка Relay Modern использует GraphQL с приложениями data-driven.

Ресурсы для изучения GraphQL:

Дополнительные материалы

7. Научитесь выполнять тестирование и чистить код

Веб-программисту на коммерческом или корпоративном проекте стоит уметь выполнять:

  • Unit tests – проверку отдельных компонентов или функций.
  • Integration tests – тестирование корректности взаимодействия компонентов.
  • End-to-end test – тестирование пользовательских потоков в браузере.
  • Другие виды тестирование, которые нужны для старших разработчиков: manual testing, snapshot testing и т.д.
Front-end developer должен писать чистый код: читаемый, без дубликатов, с минимальным использованием методов, классов и функций.

Основы чистого кода:

  • Осмысленные и логичные имена переменных, методов, функций и классов.
  • Функции стоит делать небольшими, с минимальным набором аргументов.
  • Понятный код, который не требует комментариев (в случае сложной реализации стоит прописать, что и как было сделано).

8. Запаситесь книгами по основам фронтенда

Дэвид Флэнаган, «JavaScript. Подробное руководство».


Кайл Симпсон: cерия книг «Вы не знаете Javascript».


Натан Розенталс, «Изучаем TypeScript 3».


Доминик Майерс, «Front-End Developer».


Карлос Сантана Рольдан, «React Cookbook: Create Dynamic Web Apps with React».


Крис Акино и Тодд Ганди, «Front-End Web Development: The Big Nerd Ranch Guide».


Джон Дакетт, «HTML & CSS: Design and Build Web Sites».


9. Просмотрите туториалы на YouTube

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

Если вы используете Windows, не стоит полагаться только на графический интерфейс. Чтобы упростить работу с файлами и каталогами (найти, открыть, закрыть, удалить и пр.), а также использовать неочевидные возможности ОС, потребуется знание базовых команд. Кроме старого доброго CMD рекомендуется освоить более прогрессивный PowerShell, а использующим один из дистрибутивов GNU/Linux разработчикам стоит изучить bash.

11. Изучите систему контроля версий Git и хостинг GitHub


Онлайн-хостинг для контроля версий GitHub позволяет людям по всему миру совместно работать над проектами. К тому же в репозиториях можно найти много бесплатных решений для собственных разработок.

Команды Git, которые стоит изучить
git config, git init, git commit, git clone, git status, git add, git pull, git push, git branch.

12. Следите за событиями кибербезопасности

Открытый проект OWASP собирает статистику, необходимую для обеспечения безопасности веб-приложения. Для изучения основ необходимо понимать отличия HTTPS и HTTP, какова политика защиты контента (CSP) и принципы работы с CORS.

13. Практикуйтесь как можно больше

В процессе изучения теории важно сразу применять знания на практике. Писать фрагменты кода, собирать их в единый проект (можно в выдуманный) – это поможет при трудоустройстве после обучения. Если вы создадите что-то полезное и выложите это на GitHub, всегда можно показать свои наработки потенциальному работодателю. Даже если сразу не получится пойти на позицию джуниора, не пренебрегайте бесплатной стажировкой. Начинающих специалистов на рынке труда более чем достаточно, так что стоит пользоваться любым шансом.

14. Постоянно повышайте уровень знаний

Оставаться востребованным фронтенд-разработчиком можно только если вы все время учитесь. В этом вам помогут freeCodeCamp, Codecademy.

Перечень недостающих знаний можно проверить по чек-листам:

15. Нарабатывайте софт-скилы

Продвижение по карьере, особенно в сторону менеджмента, предполагает развитие софт-скилов. Вот их примерный список:

  • навыки коммуникации помогут наладить общение с коллегами, заказчиками и деловыми партнерами;
  • работа в команде – фронтендер плотно сотрудничает с разработчиками серверной части, дизайнерами и менеджерами проекта, а значит без навыков коллективной работы он не сможет обойтись;
  • навыки сочувствия и эмпатии: общая атмосфера в коллективе важна для успеха компании;
  • готовность помогать коллегам и готовность самому просить о помощи;
  • навыки самостоятельного решения проблем;
  • навыки ведения отчетности;
  • тайм-менеджмент и самодисциплина особенно помогут при удаленной работе (фрилансе).

17. Пройдите курсы

Если вы знаете английский, можно пройти курс w3wschhools по HTML, CSS и JavaScript, или по программе Мичиганского университета заняться на coursera веб-дизайном и программированием. Популярная международная платформа предлагает множество аналогичных позиций, включая курс Duke university по основам JavaScript, HTML и CSS.

***

Если вас больше привлекает обучение на русском языке, обратите внимание на факультет frontend-разработки GeekBrains. В программе российской образовательной онлайн-платформы есть все необходимое:

  • Изучение основ программирования.
  • Базовый курс Git.
  • Верстка (HTML/CSS), в том числе библиотека Bootstrap и препроцессоры SASS/LESS.
  • Принципы ООП, JavaScript, работа с Veu.js, API Webpack, Parcel, с различным окружением, подключение библиотек.
  • Работа с ReactJS и база backend-разработки с применением ECMAScript 6, Flux, Node.js, REST API.
  • Разработка проекта с нуля до релиза. Разъяснение методологий Kanban, Scrum, Agile, принципов Countinuous Delivery и Continuous Integration.
  • Дополнительно: подготовка к техническому собеседованию, базы данных, как заняться фрилансом и искать работу.
  • Практика: создание посадочных страниц, верстка страниц и сайтов, учитывая валидность, кросплатформенность и адаптивную верстку, создание приложения для учета расходов.
16
Июл
2021

🛠 Может ли NanoID заменить UUID?

UUID – один из наиболее часто используемых при разработке ПО универсальных идентификаторов. Однако в последние несколько лет появились альтернативы, которые ставят под сомнение необходимость его существования.

Перевод публикуется с сокращениями, автор оригинальной
статьи
Charuka Herath.

Среди альтернатив занял
место NanoID – один из ведущих конкурентов, которые заменят UUID. Чтобы лучше понимать сферу его применения, в
этой статье мы поговорим об особенностях NanoID, его преимуществах и ограничениях.

NanoID и его использование

Когда дело доходит до создания
UUID или NanoID в JavaScript, становится ясно, что тут все просто – у них есть
NPM-пакеты, которые помогут вам. Все, что нужно сделать – установить библиотеку NanoID NPM с помощью команды npmi nanoid и использовать ее в своем проекте.

        import { nanoid } from 'nanoid';
model.id = nanoid();
    
Знаете ли вы, что NanoID имеет более 11 754 тыс. загрузок NPM в неделю и на 60% быстрее чем UUID?

На приведенном ниже
графике показано сравнение мы
видим тенденцию к росту NanoID по сравнению с неизменным прогрессом UUID.


Надеемся, что эти цифры
убедили вас попробовать NanoID.

Основное различие между ними простое – используемый в качестве ключа алфавит. Поскольку NanoID использует алфавит большего размера чем UUID, более короткий идентификатор может работать также, как и более длинный UUID.

1. Размер NanoID составляет всего 108 байт

В отличие от UUID, NanoID
в 4,5 раза меньше по размеру и не имеет никаких зависимостей. Кроме того,
ограничение по «весу» было использовано для уменьшения размера еще на 35%.
Это напрямую влияет на размер данных. Например, использующий NanoID объект мал и компактен для передачи и хранения данных. По мере роста приложения эти цифры становятся заметными.

2. Более безопасный

В большинстве генераторов
случайных чисел используют небезопасную Math.random(). Однако NanoID использует crypto module и Web
Crypto API
, которые являются более безопасными.
Кроме того, NanoID использует свой собственный алгоритм, называемый uniform algorithm, при реализации генератора идентификаторов вместо использования random % alphabet.

3. Быстрый и компактный

NanoID на 60% быстрее
UUID. Вместо 36 символов в алфавите UUID, NanoID имеет только 21 символ.

        0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-
    

А еще NanoID
поддерживает 14 различных языков программирования, а именно:

        C#, C++, Clojure and ClojureScript, Crystal, Dart & Flutter, Deno, Go, Elixir, Haskell, Janet, Java, Nim, Perl, PHP, Python with dictionaries, Ruby , Rust, Swift.
    

4. Совместимость

NanoID умеет работать с
PouchDB, CouchDB WebWorkers, Rollup и библиотеками, вроде React и
React-Native.
Вы можете получить уникальный идентификатор в терминале с помощью npx nanoid, но для этого вам придется соблюсти необходимое условие – установка NodeJS.


Кроме того, в наборе
инструментов Redux можно найти NanoID и использовать его следующим образом:

        import { nanoid } from ‘@reduxjs/toolkit’
console.log(nanoid()) //‘dgPXxUz_6fWIQBD8XmiSy’
    

5. Пользовательские алфавиты

Еще одной существующей
особенностью NanoID является то, что он позволяет разработчикам применять пользовательский алфавит. Вы можете изменить литералы или размер
идентификатора, как показано ниже:

        import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('ABCDEF1234567890', 12);
model.id = nanoid();
    

В приведенном выше
примере определяется пользовательский алфавит ABCDEF1234567890 с размером
идентификатора 12.

6. Отсутствие сторонних зависимостей

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

***

Ограничения и направленность на будущее

По мнению многих экспертов по StackOverflow, использование NanoID не имеет существенных недостатков или ограничений.

Нечитабельность – это основной недостаток, который многие разработчики видят в NanoID, поскольку он затрудняет отладку. Однако по сравнению с UUID NanoID намного короче и читабельнее.

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

В будущем…

NanoID постепенно
становится самым популярным генератором уникальных идентификаторов для
JavaScript, и большинство разработчиков выбирают его вместо UUID.


Приведенные выше тесты
показывают производительность NanoID по сравнению с другими
генераторами идентификаторов.

Он может генерировать более 2,2 млн. уникальных идентификаторов в секунду со своим алфавитом по умолчанию и более 1,8 млн. уникальных идентификаторов в секунду с пользовательским алфавитом.

Учитывая опыт применения, можно смело использовать
NanoID вместо UUID для любых будущих проектов, благодаря его небольшому размеру,
удобству URL, безопасности и скорости.

Дополнительные материалы:

15
Июл
2021

🛠 6 полезных фронтенд-приемов, о которых вы, возможно, не знаете

Небольшая подборка малоизвестных техник для HTML, CSS и JavaScript.

Фронтенд – это первая линия обороны веб-сайта (или, точнее, первая линия “нападения” на пользователя), поэтому у фронтендеров всегда много работы. Чтобы немножко облегчить им жизнь, мы подобрали несколько полезных, но не очень широко известных HTML, CSS и JavaScript-приемов.

1. Быстро скрыть

Чтобы спрятать DOM-элемент, вам не нужен JavaScript, достаточно нативного HTML-атрибута hidden. Эффект аналогичен добавлению стиля display: none, элемент просто исчезает со страницы.

        <p hidden>Этот параграф не виден на странице, он спрятан из HTML.</p>

    

Конечно, с псевдоэлементами такой трюк не сработает.

2. Быстро спозиционировать

Вы знакомы с CSS-свойством inset? Это сокращенный вариант для всем знакомых top, left, right и bottom. По аналогии с кратким синтаксисом свойства margin или padding вы можете задать все смещения для элемента одной строчкой.

        // До
div {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

// После
div {
  position: absolute;
  inset: 0;
}
    

Использовать краткий синтаксис полезно для уменьшения размера CSS-файла, и код так выглядит чище. Однако не забывайте, что inset – это логическое свойство, оно учитывает направление письма. То есть если на вашем сайте используется язык с направлением rtl, то лево окажется справа и наоборот.

3. Узнать скорость интернета

Вы можете легко определить скорость интернета пользователя из кода на JavaScript с помощью объекта navigator.

        navigator.connection.downlink;
    

Результат не очень 🙂 Скорость моего интернета всего 5,65 мб/сек.

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

4. Включить вибрацию на смартфоне

Да, так тоже можно. Метод vibrate() объекта window.navigator может включить режим вибрации на мобильном устройстве.

        window.navigator.vibrate(500);
    

Методу можно передать параметр – время вибрации в миллисекундах. А можно указать даже паттерн – чередование интервалов вибрации и пауз. Для этого передайте методу массив чисел.

5. Запретить pull-to-refresh

Pull-to-refresh (потяни для обновления) – это популярный паттерн мобильной разработки. Если он вам не нравится, просто запретите этот эффект с помощью CSS-свойства overscroll-behavior-y со значением contain.

        body {
 overscroll-behavior-y: contain;
}
    

Это свойство также очень полезно для организации прокрутки внутри модальных окон – оно запрещает основной странице перехватывать скролл на себя при достижении границы.

6. Запретить вставлять текст

Возможно, вы захотите запретить пользователю вставлять в поля ввода скопированный откуда-то текст (хорошо подумайте, стоит ли оно того). Это очень просто сделать отследив событие paste и вызвав его метод preventDefault().

        <input type="text"></input>
<script>
  const input = document.querySelector('input');
 
  input.addEventListener("paste", function(e){
    e.preventDefault()
  })
  
</script>
    

Упс, теперь не получится копипастить, придется писать вводить все руками.

***

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

10
Июн
2021

🎨 11 лучших поисковых систем по изображениям, которые нельзя пропустить

Иногда найти необходимую картинку – то еще занятие. Читайте подборку лучших поисковиков, которые предложат вам только самые лучшие и качественные изображения.

Перевод публикуется с…

29
Май
2021

🕵 Обучение кибербезопасности: как этичному хакеру заработать на вольных хлебах?

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

К сообществу хакеров регулярно присоединяются новые участники, и один из первых вопросов, который у них возникает: «С чего мне начать и как можно заработать деньги на этичном взломе

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

Все необходимые ресурсы можно найти в интернете, но начинать с нуля карьеру самостоятельного охотника за ошибками в Bug Bounty довольно сложно. Чтобы зарабатывать, сначала придется освоить профессию и сделать себе хоть какое-то имя в сообществе.

Если вы хотите учиться у специалиста с более чем десятилетним опытом, обратите внимание на курс Факультета кибербезопасности образовательной онлайн-платформы GeekBrains.


В любом случае – выбор способа остается за вами. Если вы предпочитаете самостоятельное обучение по книгам и лекциям в сети, почувствовать себя специалистом сможете примерно через год упорных занятий по 50+ часов в неделю. Поскольку теория без практики мертва, стоит попрактиковаться в хакерстве (или даже принять участие в соревнованиях по взлому) в специальных лабораториях.

Перечислим некоторые из них:

  1. Hack.me
  2. PortSwigger
  3. HackTheBox
  4. HackThisSite
  5. Hax.tor.hu
  6. TryHackMe
  7. pwnable.tw
  8. reversing.kr
  9. ctflearn.com
  10. csaw.io
  11. picoctf.com
  12. w3challs.com
  13. hackthebox.eu
  14. ctf.hackucf.org
  15. cryptopals.com
  16. tryhackme.com
  17. exploit.education
  18. freehackquest.com
  19. www.root-me.org
  20. www.vulnhub.com
  21. ctf.hacker101.com
  22. ctf.komodosec.com
  23. attackdefense.com
  24. Cmdchallenge.com
  25. immersivelabs.com
  26. www.hackthissite.org
  27. ctf.infosecinstitute.com
  28. www.hacking-lab.com
  29. captf.com/practice-ctf
  30. www.hacksplaining.com
  31. junior.stillhackinganyway.nl
  32. academy.hackaflag.com.br

Поскольку к новоиспеченному специалисту по кибербезопасности (этичному или белому хакеру) очередь из заказчиков не выстраивается, практикуясь во взломе и участвуя в соревнованиях, вы также нарабатываете себе портфолио. Времени на это придется потратить немало, но «волонтерство» окупится.

Как можно заработать новичку?

Опытные независимые исследователи безопасности часто имеют солидную клиентуру – такие хакеры-фрилансеры могут зарабатывать миллионы долларов в год. Если вы получили солидный опыт бесплатной работы за портфолио и о высшей лиге пока только мечтаете, начните с участия в программах Bug Bounty. Искать ошибки в информационных системах и получать от компаний вознаграждение – не самый плохой старт для новичка.

Кто они – охотники за багами?
Разбирающиеся в тонкостях кибербезопасности специалисты часто занимаются поиском уязвимостей в информационных системах и различных приложениях – они известны как охотники за ошибками (багами). Существует множество платформ Bug Bounty, где охотники получают вознаграждение за свой труд, даже не являясь штатными сотрудниками компаний или высокооплачиваемыми фрилансерами. Программы Bug Bounty позволяют хакерам обнаруживать и исправлять ошибки до того, как о них узнает широкая публика – таким способом предотвращают инциденты информационной безопасности.

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

Программы бывают частными (только по приглашениям), когда отчеты остаются конфиденциальными, или общедоступными (к которым может присоединиться любой желающий). Иногда они проходят в течение определенного времени, но чаще не имеют даты окончания. Главный их недостаток – вознаграждение получает только тот хакер, который обнаружит баг первым. Остальные остаются без денег.

Где можно заработать?

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

  1. Министерство обороны США
  2. Mail.Ru
  3. IBM
  4. SpaceX
  5. Apple
  6. Facebook
  7. Google
  8. Microsoft
  9. Twitter
  10. DropBox
Крупные компании платят хорошие деньги, но получить их весьма непросто. Начать стоит с более простых задач и относительно небольших гонораров.

Качество отчета


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

  1. Подробное объяснение найденной проблемы, включая четкие шаги воспроизведения или действующее подтверждение концепции (POC).
  2. Снимки экрана и/или видео иногда могут помочь службам безопасности воспроизвести проблему. Большинство хакеров предпочитает текстовые описания, но снимки экрана и видео можно использовать как дополнительные материалы.
  3. Воздействие (уровень важности) уязвимости: что может произойти, если эту ошибку используют злоумышленники? Описание важности проблемы поможет специалистам компании расставить приоритеты по реагированию и исправлению.

Пример: Shopify: удаленное выполнение кода на kitcrm с использованием массового обновления клиентов приоритетных продуктов

Бонус

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

  1. Slavehack.com
  2. Hacker-project.com
  3. Hackers-edge.com
  4. S0urce.io
  5. Hackerexperience.com
  6. 2hack.net
  7. Gameofhacks.com
  8. Hackertest.net
  9. Hackerforever.net
  10. hackertyper.net
***

Едва ли вас заинтересует участие в программах Bug Bounty как форма постоянной занятости на многие годы – в режиме фултайм ошибки без гарантии оплаты ищет только пятая часть вольных хакеров. Прочие повышают уровень и уходят на фриланс, выбрав одну из многих доступных в сфере информационной безопасности специализаций и набрав заказчиков. Если вы хотите узнать о способах заработать на вольных хлебах подробнее, обратите внимание на Факультет информационной безопасности онлайн-академии GeekBrains. Помимо прочего слушателей курса научат работать в программах Bug Bounty, а в число преподавателей входят опытные охотники за уязвимостями.

19
Май
2021

🕸 ТОП-5 популярных технологий для создания сайтов: просто и понятно для новичков

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

29
Апр
2021

🕸 21 лучший метод выведет ваши навыки проектирования API на новый уровень

Чтобы не разочаровываться в ужасном API и не играть в угадайку на каждом шагу, стоит использовать лучшие известные практики. Рассмотрим их в небольшом обзоре.

Перевод публикуется с сокращениями, автор оригинальной статьи Mohammad Faisal.

Немного терминологии

Любой API следует так называемому ресурсно-ориентированному
дизайну и состоит из трех ключевых концепций.

  • ресурс: часть данных, например, User;
  • коллекция: группа ресурсов, например, List of users;
  • URL: местоположение ресурса или коллекции, например, /user.

1. Kebab-case для URL-адресов

Если вы хотите получить
список заказов.

Плохо:

        /systemOrders или /system_orders
    

Хорошо:

        /system-orders
    

2. CamelCase для параметров

Применяйте, если хотите
получить товары из определенного магазина.

Плохо:

        /system-orders/{order_id} или /system-orders/{OrderId}
    

Хорошо:

        /system-orders/{orderId}
    

3. Множественное число, указывающее на коллекцию

Если необходимо получить
всех пользователей системы.

Плохо:

        GET /user или GET /User
    

Хорошо:

        GET /users
    

4. URL начинается с коллекции и заканчивается идентификатором

Если хотите сохранить
концепцию единой и последовательной.

Плохо:

        GET /shops/:shopId/category/:categoryId/price
    

Это плохо, потому что здесь
описано свойство, а не ресурс.

Хорошо:

        GET /shops/:shopId/ или GET /category/:categoryI
    

5. Не используйте глаголы в URL ресурса

Не используйте глаголы в URL для выражения действий. Вместо этого примените
описанные ниже методы.

Плохо:

        POST /updateuser/{userId} или GET /getusers
    

Хорошо:

        PUT /user/{userId}
    

6. Используйте глаголы в URL для Non-Resource

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

Хорошо:

        POST /alerts/245743/resend
    

7. Используйте camelCase для свойства JSON

Если у вас есть тело запроса
или ответ в JSON, имена свойств должны быть в camelCase.

Плохо:

        {
   user_name: «Programmer's library»
   user_id: «1»
}

    

Хорошо:

        {

   userName: «Programmer's library»

   userId: «1»

}
    

8. Мониторинг

Службы HTTP RESTful должны
реализовывать конечные точки API /health,
/version и /metrics, предоставляющие следующую информацию:

  • /health – отвечает на запросы с кодом состояния 200 OK;
  • /version – отвечает на запрос номером версии;
  • /metrics – эта конечная точка будет предоставлять различные показатели, например, среднее время отклика.

Настоятельно рекомендуем использовать
конечные точки /debug и /status.

9. Не используйте table_name для имени ресурса

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

Плохо:

        product_order
    

Хорошо:

        product-orders
    

10. Применяйте инструменты проектирования

Существует много хороших
инструментов проектир
ования API:

  • API Blueprint
  • Swagger

Наличие хорошей и
подробной документации обеспечивает отличный клиентский опыт для пользователей
API.

11. Используйте порядковый номер в качестве версии

Всегда указывайте номер
версии для API. Номер версии должен быть v1, v2 и т. д.

Хорошо:

        http://api.domain.com/v1/shops/3/products
    

Если API используется
внешними сущностями, изменение конечной точки может нарушить их
функциональность, поэтому использование версий обязательно.

12. Выводите в ответе общее количество ресурсов

Если API возвращает
список объектов, всегда включайте общее количество ресурсов в ответ.

Плохо:

        {

пользователи: [ .

..

]

}
    

Хорошо:

        {

пользователи: [ .

..

],

всего: 34

}
    

13. Принимайте параметры ограничения и смещения

Всегда принимайте
параметры ограничения и смещения в операциях GET.

Хорошо:

        GET /shops?offset=5&limit=5
    

Это необходимо для пагинации
на фронтенде.

14. Получаем поля параметров запроса

Следует учитывать объем
возвращаемых данных. Добавьте параметр fields,
чтобы предоставить только необходимые поля из вашего API.

Пример:

Вернуть только название,
адрес и контакты магазинов.

        GET /shops?fields=id,name,address,contact
    

В некоторых случаях это поможет
уменьшить размер ответа.

15. Не передавайте в URL токены аутентификации

Это очень плохая
практика, потому что URL часто регистрируются и, следовательно, маркер
аутентификации также будет регистрироваться без необходимости.

Плохо:

        GET /shops/123?token=some_kind_of_authenticaiton_token
    

Хорошо:

Вместо этого передайте их
в заголовке:

        Authorization: Bearer xxxxxx, Extra yyyyy
    

Кроме того, токены
авторизации должны быть недолговечными.

16. Проверка Content-Type

Сервер не должен
принимать content-type. Например,
если вы принимаете application/x-www-form-urlencoded,
злоумышленник может создать форму и запустить простой запрос POST.

Всегда валидируйте тип контента, а если хотите использовать content-type по умолчанию, используйте application/json.

17. Использование методов HTTP для функций CRUD

Следующие методы служат для
описания CRUD-функций:

  • GET: получение представления ресурса.
  • POST: создание новых ресурсов и подресурсов.
  • PUT: обновление существующих ресурсов.
  • PATCH: обновление существующих ресурсов, но только тех полей, которые были описаны (остальные остаются без изменений).
  • DELETE: удаление существующих ресурсов.

18. Применение отношений в URL для вложенных ресурсов

Вот некоторые
практические примеры:

  • GET /shops/2/products: получить список всех продуктов из магазина 2.
  • GET /shops/2/products/31: получить подробную информацию о продукте 31, из магазина 2.
  • DELETE /shops/2/products/31: удалить продукт 31 из магазина 2.
  • PUT /shops/2/products/31: обновить информацию о продукте 31 (использовать только URL ресурса, а не коллекцию).
  • POST /shops: создать новый магазин и вернуть сведения о нем.

19. CORS

Поддерживайте заголовки
CORS (Cross-Origin Resource Sharing) для всех общедоступных API.

Рассмотрите возможность поддержки разрешенного CORS-источника « * » и принудительной авторизации с помощью OAuth-токенов. Избегайте объединения учетных данных пользователя с валидацией происхождения.

20. Безопасность

Применяйте протокол HTTPS
(зашифрованный TLS) ко всем конечным точкам, ресурсам и службам.

HTTPS должен быть у всех колбеков, эндпоинтов, push-уведомлений и веб-хуков.

21. Ошибки

Ошибки возникают, когда
клиент делает неправильный запрос к службе или передает службе неправильные
данные, а та отклоняет запрос. Популярные проблемы: неверные учетные
данные, неправильные параметры, неизвестные идентификаторы версий и т. д.

При отклонении запроса клиента по причине ошибок службы возвращают коды HTTP – 4xx.

Заключение

Вот и все – поздравляем,
если вы зашли так далеко! Надеемся, вы кое-чему научились и будете применять рекомендации статьи в своих проектах. Удачи!

Дополнительные материалы:

24
Апр
2021

🕸 Блоги и комьюнити по веб-разработке в России и за рубежом: 43 ресурса, актуальных в 2021 году

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

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

Мы собрали список ресурсов, который поможет как начинающим, так и уже состоявшимся разработчикам.


HTML

  • htmlbook – пожалуй мой любимый русскоязычный ресурс по HTML. Блог содержит много полезных статей на различные темы: от обучения до трудоустройства. Информация об HTML, CSS, веб-дизайну, графике и созданию сайтов. Там же есть неплохой форум.
  • htmlacademy – бесплатные конспекты лекций и докладов, статьи про карьеру и советы для новичков.
  • htmlforums.net – сообщество разработчиков HTML и CSS.
  • codeforum.org – ресурс, который помогает разработчикам с любым уровнем навыков.

CSS

  • css-live.ru – русскоязычное сообщество, посвященное HTML, CSS и JavaScript.
  • cssauthor.com – блог о мобильной разработке, содержащий бесплатные материалы по дизайну пользовательского интерфейса, ресурсы, статьи, инструменты и многое другое.
  • css-tricks.com – полезные статьи и руководства по всем вопросам, связанным с CSS, включая определяющий важные термины CSS альманах. На сайте также доступны руководства, которые помогут читателям получить опыт в веб-разработке.
  • CSS {IRL} – блог о технологиях создания интерфейсов с особым упором на CSS.
  • codrops – учебники, статьи и обзоры по вопросам, связанным с CSS, включая полезную библиотеку терминов для начинающих.

JavaScript

  • reacttraining – семинары, корпоративные тренинги и даже информационные бюллетени обо всем, что нужно знать изучающим React. Статьи в блоге обычно короткие, но содержат много полезной информации.
  • Echo JS – управляемый сообществом новостной сайт, полностью ориентированный на разработку JavaScript, HTML5 и новости фронтенда.

Официальные блоги платформ и компаний

  • JetBrains – блог интерактивной среды разработки для frontend и серверного JavaScript.
  • w3.org – блог Консорциума Всемирной паутины, организации, которая разрабатывает и внедряет технологические стандарты Интернета. Ресурс предназначен для обсуждений различных вопросов в W3C и в мировом веб-сообществе. Содержит объявления, выпуски веб-стандартов и образовательные материалы.
  • nodejs – официальный блог разработчиков среды выполнения JavaScript, построенной на движке Chrome V8.
  • blog.jquery – официальный блог jQuery. Исчерпывающий источник новостей об одном из самых популярных интерфейсных инструментов.
  • BetterStudio – все о WordPress от компании с десятилетней историей.

  • CodePen – платформа, которая позволяет писать код в браузере и видеть результаты. В блоге публикуются различные объявления, новые и обновленные функции, советы и рекомендации, обзоры и многое другое.
  • ChromeDevTools – новости, последние обновления и полезные расширения для разработчиков Chrome.
  • web.dev – новости для разработчиков от команды Chrome Developer Relations.
  • WebKit – официальный блог самого популярного движка для отображения веб-страниц.
  • MozillaHacks – официальный блог браузера Mozilla Firefox для разработчиков.
  • VisualStudioCode – официальный блог одного из популярных редакторов кода.
  • merehead – блог о веб-разработке и дизайне компании Merehead.

Авторские блоги

  • css.yoksel.ru – авторский блог Юлии Бухваловой про CSS и SVG. Его цель – помочь читателям разобраться в новых технологиях и познакомиться поближе со старыми, а также сохранить находки и законспектировать изученное.
  • maxgraph – авторский блог о веб-разработке. Лайфхаки, полезные сервисы, софт, а также внутренняя кухня фриланса.
  • anton.shevchuk – блог про PHP, JavaScript, jQuery и «всяко-разно о web-разработке».
  • matuzo.at – блог Мануэля Матузовича, профессионального веб-разработчика, который преподает HTML и CSS в Венском институте SAE, ZID в Вене и FH Salzburg.
  • meyerweb – блог Эрика Мейера, эксперта в области HTML и CSS, автора множества статей и книг, создателя нескольких полезных инструментов и ресурсов.
  • flaviocopes.com – блог Флавио Коупса, про React, Vue, Svelte, Next.js.

  • taniarascia – блог Тани Расции, специалиста по OpenSource и эксперта в Google. Специализируется на JavaScript/​TypeScript.
  • coryrylan – сайт эксперта по разработке Google и фронтенд-разработчика. Кори Рилан предлагает полезные статьи и руководства, которые помогают читателям развивать навыки и становиться лучшими разработчиками.
  • davidwalsh – блог Дэвида Уолша. Активный веб-разработчик делится советами о том, как читатели могут улучшить свои навыки. Уолш помогает с множеством интерфейсных инструментов веб-разработки, вроде HTML и JavaScript.
  • meiert – авторский блог о ремесле веб-разработки, особенно об оптимизации HTML и CSS.
  • jakearchibald – авторский блог Джека Арчибальда. Джек – веб-евангелист и представитель браузера Google Chrome, один из лучших экспертов компании, автор множества докладов на актуальные темы.

Разное

  • webdevblog – блог о программировании и веб-разработке.
  • stackoverflow – крупнейшее и пользующееся у профессионалов наибольшим доверием онлайн-сообщество, где разработчики могут учиться, делиться знаниями и строить карьеру.
  • LogRocket – блог дает владельцам полезные советы и рекомендации по улучшению их сайтов.
  • freeCodeCamp – блог некоммерческой организации, которая состоит из интерактивной обучающей веб-платформы, онлайн-форума сообщества, чатов, онлайн-публикаций и местных организаций.
  • SitePoint – блог публикует статьи для веб-разработчиков, включающие советы по улучшению навыков программирования, а также интервью с опытными профессионалами. Также содержит доску объявлений и библиотеку полезных книг.

  • codeburst – место, где можно узнать о веб-разработке все и найти хорошие курсы по программированию.
  • ultimatecourses – полезные и подробные курсы по Angular, TypeScript, RxJS, JavaScript, React и AngularJS от опытных разработчиков.
  • codewall – сайт был создан, чтобы помогать, мотивировать и поощрять любителей кода. Здесь вы найдете руководства по программированию и веб-разработке, новости, юмор и множество бесценных ресурсов.
  • sidebar – 5 лучших ссылок по веб-дизайну, каждый день.
Рекомендуем также ознакомиться с прошлогодней подборкой сайтов, блогов и комьюнити по веб-разработке. Большинство из них все еще актуальны.

Заключение

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

***

Если вы хотите научиться веб-разработке с нуля, стоит обратить внимание на курс Факультета веб-разработки GeekBrains. За 15 месяцев онлайн-обучения вы пройдете путь от создания макетов до оптимизации баз данных и алгоритмов, а также получите практический опыт и добавите к резюме 5 реализованных проектов. Благодаря оптимально подобранной программе новички освоят высокооплачиваемую профессию, а практикующие специалисты смогут перейти в более востребованное направление и увеличить заработки. Успешно окончившим курс студентам GeekBrains выдает свидетельство о профессиональной подготовке, а также помогает с трудоустройством.

24
Апр
2021

🕸 Блоги и комьюнити по веб-разработке в России и за рубежом: 43 ресурса, актуальные в 2021 году

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

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

Мы собрали список ресурсов, который поможет как начинающим, так и уже состоявшимся разработчикам.


HTML

  • htmlbook – пожалуй мой любимый русскоязычный ресурс по HTML. Блог содержит много полезных статей на различные темы: от обучения до трудоустройства. Информация об HTML, CSS, веб-дизайну, графике и созданию сайтов. Там же есть неплохой форум.
  • htmlacademy – бесплатные конспекты лекций и докладов, статьи про карьеру и советы для новичков.
  • htmlforums.net – сообщество разработчиков HTML и CSS.
  • codeforum.org – ресурс, который помогает разработчикам с любым уровнем навыков.

CSS

  • css-live.ru – русскоязычное сообщество, посвященное HTML, CSS и JavaScript.
  • cssauthor.com – блог о мобильной разработке, содержащий бесплатные материалы по дизайну пользовательского интерфейса, ресурсы, статьи, инструменты и многое другое.
  • css-tricks.com – полезные статьи и руководства по всем вопросам, связанным с CSS, включая определяющий важные термины CSS альманах. На сайте также доступны руководства, которые помогут читателям получить опыт в веб-разработке.
  • CSS {IRL} – блог о технологиях создания интерфейсов с особым упором на CSS.
  • codrops – учебники, статьи и обзоры по вопросам, связанным с CSS, включая полезную библиотеку терминов для начинающих.

JavaScript

  • reacttraining – семинары, корпоративные тренинги и даже информационные бюллетени обо всем, что нужно знать изучающим React. Статьи в блоге обычно короткие, но содержат много полезной информации.
  • Echo JS – управляемый сообществом новостной сайт, полностью ориентированный на разработку JavaScript, HTML5 и новости фронтенда.

Официальные блоги платформ и компаний

  • JetBrains – блог интерактивной среды разработки для frontend и серверного JavaScript.
  • w3.org – блог Консорциума Всемирной паутины, организации, которая разрабатывает и внедряет технологические стандарты Интернета. Ресурс предназначен для обсуждений различных вопросов в W3C и в мировом веб-сообществе. Содержит объявления, выпуски веб-стандартов и образовательные материалы.
  • nodejs – официальный блог разработчиков среды выполнения JavaScript, построенной на движке Chrome V8.
  • blog.jquery – официальный блог jQuery. Исчерпывающий источник новостей об одном из самых популярных интерфейсных инструментов.
  • BetterStudio – все о WordPress от компании с десятилетней историей.

  • CodePen – платформа, которая позволяет писать код в браузере и видеть результаты. В блоге публикуются различные объявления, новые и обновленные функции, советы и рекомендации, обзоры и многое другое.
  • ChromeDevTools – новости, последние обновления и полезные расширения для разработчиков Chrome.
  • web.dev – новости для разработчиков от команды Chrome Developer Relations.
  • WebKit – официальный блог самого популярного движка для отображения веб-страниц.
  • MozillaHacks – официальный блог браузера Mozilla Firefox для разработчиков.
  • VisualStudioCode – официальный блог одного из популярных редакторов кода.
  • merehead – блог о веб-разработке и дизайне компании Merehead.

Авторские блоги

  • css.yoksel.ru – авторский блог Юлии Бухваловой про CSS и SVG. Его цель – помочь читателям разобраться в новых технологиях и познакомиться поближе со старыми, а также сохранить находки и законспектировать изученное.
  • maxgraph – авторский блог о веб-разработке. Лайфхаки, полезные сервисы, софт, а также внутренняя кухня фриланса.
  • anton.shevchuk – блог про PHP, JavaScript, jQuery и «всяко-разно о web-разработке».
  • matuzo.at – блог Мануэля Матузовича, профессионального веб-разработчика, который преподает HTML и CSS в Венском институте SAE, ZID в Вене и FH Salzburg.
  • meyerweb – блог Эрика Мейера, эксперта в области HTML и CSS, автора множества статей и книг, создателя нескольких полезных инструментов и ресурсов.
  • flaviocopes.com – блог Флавио Коупса, про React, Vue, Svelte, Next.js.

  • taniarascia – блог Тани Расции, специалиста по OpenSource и эксперта в Google. Специализируется на JavaScript/​TypeScript.
  • coryrylan – сайт эксперта по разработке Google и фронтенд-разработчика. Кори Рилан предлагает полезные статьи и руководства, которые помогают читателям развивать навыки и становиться лучшими разработчиками.
  • davidwalsh – блог Дэвида Уолша. Активный веб-разработчик делится советами о том, как читатели могут улучшить свои навыки. Уолш помогает с множеством интерфейсных инструментов веб-разработки, вроде HTML и JavaScript.
  • meiert – авторский блог о ремесле веб-разработки, особенно об оптимизации HTML и CSS.
  • jakearchibald – авторский блог Джека Арчибальда. Джек – веб-евангелист и представитель браузера Google Chrome, один из лучших экспертов компании, автор множества докладов на актуальные темы.

Разное

  • webdevblog – блог о программировании и веб-разработке.
  • stackoverflow – крупнейшее и пользующееся у профессионалов наибольшим доверием онлайн-сообщество, где разработчики могут учиться, делиться знаниями и строить карьеру.
  • LogRocket – блог дает владельцам полезные советы и рекомендации по улучшению их сайтов.
  • freeCodeCamp – блог некоммерческой организации, которая состоит из интерактивной обучающей веб-платформы, онлайн-форума сообщества, чатов, онлайн-публикаций и местных организаций.
  • SitePoint – блог публикует статьи для веб-разработчиков, включающие советы по улучшению навыков программирования, а также интервью с опытными профессионалами. Также содержит доску объявлений и библиотеку полезных книг.

  • codeburst – место, где можно узнать о веб-разработке все и найти хорошие курсы по программированию.
  • ultimatecourses – полезные и подробные курсы по Angular, TypeScript, RxJS, JavaScript, React и AngularJS от опытных разработчиков.
  • codewall – сайт был создан, чтобы помогать, мотивировать и поощрять любителей кода. Здесь вы найдете руководства по программированию и веб-разработке, новости, юмор и множество бесценных ресурсов.
  • sidebar – 5 лучших ссылок по веб-дизайну, каждый день.
Рекомендуем также ознакомиться с прошлогодней подборкой сайтов, блогов и комьюнити по веб-разработке. Большинство из них все еще актуальны.

Заключение

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

***

Если вы хотите научиться веб-разработке с нуля, стоит обратить внимание на курс Факультета веб-разработки GeekBrains. За 15 месяцев онлайн-обучения вы пройдете путь от создания макетов до оптимизации баз данных и алгоритмов, а также получите практический опыт и добавите к резюме 5 реализованных проектов. Благодаря оптимально подобранной программе новички освоят высокооплачиваемую профессию, а практикующие специалисты смогут перейти в более востребованное направление и увеличить заработки. Успешно окончившим курс студентам GeekBrains выдает свидетельство о профессиональной подготовке, а также помогает с трудоустройством.

20
Апр
2021

🕸 Golang для веб-разработки: примеры использования

Разбираем преимущества и недостатки языка Go для веб-разработки и рассказываем о написанных на нем (и для него) приложениях, библиотеках и фреймворках, которые можно использовать в собственных проектах.

Go особенности и немного истории

Go (Golang) представляет собой компилируемый, многопоточный, статически типизированный язык. Он был разработан командой Google в 2007 году для улучшения производительности высоконагруженных серверных приложений.

Первоначально к языку предъявлялись следующие требования:

  • Он должен работать в большом масштабе для программ с большим количеством зависимостей.
  • Он должен быть понятен знакомым с C программистам. Многие разработчики Google хорошо владели процедурными языками из семейства C. Необходимость быстро обучить специалистов требовала, чтобы Go не имел радикальных отличий от них.
  • Он должен быть современным. C, C++ и в некоторой степени Java – довольно старые. Они были разработаны до появления многоядерных машин, сетей и веб-приложений. Особенности современного мира требуют внедрять новые подходы вроде встроенного параллелизма.

Go – отличный вариант для создания простых, но эффективных веб-сервисов. Разберем вкратце основные плюсы и минусы этого языка для веб-разработки.


Преимущества

  • Высокая скорость. Go быстро компилирует проекты и может применяться даже для редактирования кода прямо в интернете.
  • Совместимость с C. Это позволяет использовать многочисленные библиотеки, созданные для одного из самых распространенных языков.
  • Широкие возможности из коробки. Расширенная стандартная библиотека охватывает множество областей. В Go есть полностью рабочий веб-сервер и многое другое.
  • Документация как стандартная функция. Программисты могут легко документировать код и генерировать удобочитаемые данные прямо из комментариев.
  • Сборка мусора (автоматическое управление памятью) – ключевая функция языка Go. Он дает контроль над распределением памяти и упрощает оптимизацию приложений.
  • Масштабируемость и параллелизм. По мере развития приложений и сервисов приходится одновременно решать множество мелких задач, вроде доставки HTML в отдельные веб-браузеры. Go имеет множество встроенных функций, связанных с параллелизмом: в первую очередь goroutines и каналы. Goroutines – функции, которые выполняются одновременно с другими. Каналы позволяют различным goroutines взаимодействовать друг с другом.

Подробнее о возможностях Golang вы можете узнать из этой статьи.

Недостатки

  • Отсутствие параметрического полиморфизма для универсального программирования приводит к дублированию кода или небезопасным преобразованиям типов.
  • Нулевой интерфейс не равен интерфейсу нулевого объекта, что в сочетании с отсутствием алгебраических типов приводит к трудностям при обработке сбоев и базовых случаев.
  • Go не допускает появления открывающей скобки на отдельной строке, что заставляет программистов использовать один и тот же стиль скобок.
  • Семантика файлов в стандартной библиотеке Go в значительной степени основана на семантике POSIX и они плохо отображаются на платформе Windows.
Рекомендуем также ознакомиться самыми распространенными подводными камнями Go, а также сравнением Python и Golang по различным характеристикам.

Примеры использования Go

Go применяется в веб-разработке для решения разных задач. Мы собрали примеры самых интересных приложений, библиотек и фреймворков, чтобы поближе познакомить вас с возможностями языка.

Аутентификация

  • Authboss – модульная система, которая позволяет добавить в приложение функции аутентификации и авторизации.
  • Casbin – библиотека авторизации, поддерживающая модели контроля доступа, включая ACL, RBAC и ABAC.
  • Go-email-normalizer – библиотека Go для обеспечения канонического представления адреса электронной почты.
  • Go-Guardian – эта библиотека обеспечивает простой, понятный и идиоматический способ создания современного API и веб-аутентификации. Она поддерживает LDAP, базовую аутентификацию, токен-носитель и аутентификацию на основе сертификатов.
  • Go-oauth2-server – автономный сервер OAuth2, написанный на Golang и соответствующий спецификациям.
  • Permissions2 – библиотека для отслеживания пользователей, состояний входа и разрешений. Использует безопасные файлы cookie и bcrypt.

Боты

  • Ephemeral-roles – бот Discord для управления эфемерными ролями на основе присутствия участника голосового канала.
  • Go-chat-bot – бот для IRC, Slack и Telegram, написанный на Go.
  • Go-tgbot – оболочка API-интерфейса Pure Golang Telegram Bot, созданная из файла swagger, сеансового маршрутизатора и промежуточного программного обеспечения.
  • Hanu – фреймворк для написания ботов Slack.
  • Slack-bot – готовый к использованию Slack Bot для ленивых разработчиков: пользовательские команды, Jenkins, Jira, Bitbucket, Github.
  • Tenyks – сервис-ориентированный IRC-бот, использующий Redis и JSON для обмена сообщениями.

Базы данных

  • Bbolt – встроенная база ключей/значений для Go.
  • Bcache – согласованная библиотека Go для распределенного кэша в памяти.
  • Bitcask – это встраиваемая, постоянная и быстрая база данных типа ключ-значение (KV), написанная на чистом Go. Отличается предсказуемой производительностью чтения/записи, низкой задержкой и высокой пропускной способностью благодаря расположению битовой маски на диске (LSM + WAL).
  • CovenantSQL – база данных SQL на блокчейне.
  • Databunker – служба хранения личной информации, созданная в соответствии с GDPR и CCPA.
  • Hare – простая система управления базой данных, в которой каждая таблица хранится в виде текстового файла JSON с разделителями-строками.
  • Ledisdb – высокопроизводительный NoSQL, подобный Redis и основанный на LevelDB.
  • Rqlite – легкая распределенная реляционная база данных, построенная на SQLite.
  • Go-mysql – набор инструментов Go для обработки протокола MySQL и репликации.
  • Kingshard – высокопроизводительный прокси для MySQL на базе Golang.
  • Pg_timetable – расширенное планирование для PostgreSQL.

DNS

  • DNS – библиотека Go для работы с DNS.
  • Go-powerdns – привязки API PowerDNS для Golang.
  • Mdns – простая клиент-серверная библиотека mDNS (Multicast DNS) для Golang.
  • DDNS – персональный клиент DDNS с DNS Digital Ocean Networking в качестве серверной части.
  • Dyndns – процесс Background Go для регулярной автоматической проверки IP-адреса и внесения обновлений в одну или несколько динамических записей DNS для доменов Google при каждом изменении.
  • GoDNS – написанный на Go клиентский инструмент динамического DNS, поддерживающий DNSPod и HE.net.

Почта

  • Chasquid – SMTP-сервер, написанный на Go.
  • Email – надежная и гибкая библиотека электронной почты для Go.
  • Go-dkim – библиотека DKIM для подписания и проверки электронной почты.
  • Go-imap – библиотека IMAP для клиентов и серверов.
  • Go-simple-mail – очень простой пакет для отправки электронных писем с SMTP Keep Alive и двумя таймаутами: Connect и Send.
  • Hectane – легкий SMTP-клиент, предоставляющий HTTP API.
  • MailHog – тестирование электронной почты и SMTP с веб-интерфейсом и интерфейсом API.

Формы

  • Binding – связывает форму и данные JSON из запроса net/http со структурой.
  • Form – декодирует url.Values ​​в значения Go и кодирует значения Go в url.Values. Поддержка Dual Array и Full map.
  • Forms – не зависящая от платформы библиотека для анализа и проверки данных форм, которая поддерживает составные формы и файлы.
  • Qs – модуль Go для кодирования структур в параметры URL.

Веб GUI

  • App – пакет для создания приложений с GO, HTML и CSS. Поддерживает MacOS (поддержка Windows в процессе разработки).
  • Go-sciter – встраиваемый движок HTML/CSS/скриптов для разработки пользовательского интерфейса современного рабочего стола.
  • Webview – кроссплатформенное окно веб-просмотра с простыми двусторонними привязками JavaScript (Windows/macOS/Linux).

Обмен сообщениями

  • Asynq – простая, надежная и эффективная распределенная очередь задач для Go, построенная на основе Redis.
  • Beaver – сервер обмена сообщениями в реальном времени для создания масштабируемых уведомлений в приложениях, многопользовательских игр, приложений чата в браузере и программах для мобильных устройств.
  • Confluent-kafka-go – клиент Golang от Confluent для Apache Kafka и платформы Confluent.
  • Drone-line – отправка уведомлений Line с использованием двоичного кода, докера или Drone CI.
  • Glue – надежная библиотека сокетов Go и Javascript.
  • Gorush – сервер push-уведомлений с использованием APNs2 и google GCM.
  • Jazz – простой уровень абстракции RabbitMQ для администрирования очередей, публикации и использования сообщений.

Сети

  • DHCP6 – реализует сервер DHCPv6, как описано в RFC 3315.
  • Fortio – библиотека нагрузочного тестирования и инструмент командной строки, расширенный эхо-сервер и веб-интерфейс. Позволяет указать заданную посекундную нагрузку и записать гистограммы задержки, а также другую полезную статистику и построить график. Поддерживает TCP, HTTP и gRPC.
  • Ftpserverlib – полнофункциональная библиотека FTP-сервера.
  • Gmqtt – гибкая, высокопроизводительная библиотека брокера MQTT, которая полностью реализует протокол MQTT V3.1.1.
  • Go-stun – реализация клиента STUN (RFC 3489 и RFC 5389).
  • Goshark – использует tshark для декодирования IP-пакета и создания структуры данных для его анализа.
  • Gosnmp – собственная библиотека Go для работы с SNMP.

HTTP-клиенты

  • Heimdall – усовершенствованный HTTP-клиент с возможностями повтора и hystrix.
  • Resty – простой HTTP- и REST-клиент для Go, вдохновленный Ruby rest-client.
  • Sling – клиентская библиотека Go HTTP для создания и отправки запросов API.

Серверные приложения

  • Algernon – веб-сервер HTTP/2 со встроенной поддержкой Lua, Markdown, GCSS и Amber.
  • Fider – открытая платформа для сбора и систематизации отзывов клиентов.
  • Jackal – XMPP-сервер, написанный на Go.
  • RoadRunner – высокопроизводительный сервер приложений PHP, балансировщик нагрузки и менеджер процессов.

Тестирование

  • Failpoint – реализация точек отказа для Golang.
  • Rod – драйвер Devtools для упрощения веб-автоматизации и парсинга.
  • Testsql – генерирует тестовые данные из файлов SQL перед тестированием и очищает их после завершения.
  • Testfixtures – помощник для Rails-подобных тестовых инструментов, предназначенных для тестирования приложений баз данных.
  • Restit – микро-фреймворк для написания интеграционного теста RESTful API.
  • Assert – базовая библиотека утверждений, используемая вместе с собственным тестированием Go.

Сторонние API

  • Airtable – клиентская библиотека Go для API Airtable.
  • Anaconda – клиентская библиотека Go для API Twitter 1.1.
  • Aws-sdk-go – официальный SDK AWS для языка программирования Go.
  • Discordgo – привязки Go для Discord Chat API.
  • Ethrpc – привязки Go для Ethereum JSON RPC API.
  • Gami – библиотека Go для интерфейса Asterisk Manager.
  • Geo-golang – библиотека Go для доступа к Google Maps, MapQuest, Nominatim, OpenCage, Bing, Mapbox и API геокодирования, а также обратного геокодирования OpenStreetMap.
  • Github – библиотека Go для доступа к GitHub REST API v3.
  • Medium – SDK Golang для API OAuth2 Medium.
  • Patreon-go – библиотека Go для Patreon API.

Веб-фреймворки

  • Aero – высокопроизводительный веб-фреймворк для Go, который набирает высшие баллы в Lighthouse.
  • Banjo – очень простой и быстрый веб-фреймворк для Go.
  • Fiber – веб-фреймворк, вдохновленный Express.js и построенный на Fasthttp.
  • Flamingo Commerce – предоставление функций электронной коммерции с использованием чистой архитектуры (вроде DDD), а также портов и адаптеров, которые можно использовать для создания гибких приложений.
  • Gizmo – набор микросервисных, используемый New York Times.
  • Goyave – полнофункциональная инфраструктура REST API, нацеленная на чистый код и быструю разработку.
  • Microservice – фреймворк для создания микросервисов.
  • Rex – библиотека для модульной разработки, основанная на gorilla/mux и полностью совместимая с net/http.
  • WebGo – микро-фреймворк для создания веб-приложений

WebAssembly

  • Dom – библиотека DOM.
  • Go-canvas – библиотека для использования HTML5 Canvas в коде go.
  • Tinygo – компилятор Go: микроконтроллеры, WebAssembly и инструменты командной строки на основе LLVM.
  • Vert – взаимодействие между значениями Go и JS.
  • Wasmbrowsertest – запускает тесты Go WASM в вашем браузере.
  • Webapi – привязки для DOM и HTML, созданные из WebIDL.

Заключение

Наш далеко не полный список приложений, инструментов и библиотек призван проиллюстрировать возможности Golang для веб-разработки. Если вы решили освоить язык самостоятельно или улучшить свои знания, рекомендуем ознакомиться со списком из 30 лучших книг. Для более системного изучения стоит обратить внимание на курсы онлайн-академии GeekBrains. За 12 месяцев опытные преподаватели научат вас писать на Go высоконагруженные приложения и безопасные масштабируемые сервисы. График занятий (2 раза в неделю) идеально подходит не только для новичков, но для программистов, занимающихся еще одним языком в свободное время. Учебная программа ориентирована на практическую работу в команде, а успешно окончившие курс слушатели смогут добавить к портфолио 5 реализованных проектов и получат помощь в трудоустройстве.

17
Апр
2021

🍏 Взаимодействие SwiftUI с вебом. Часть вторая: Web Navigation

В предыдущей статье мы создали WebView и подгрузили в него сайт proglib.io. Сегодня займемся пользовательским интерфейсом приложения, навигацией и получением информации с веб-страницы в Swift c помощью JavaScript.

03
Апр
2021

🍏 Взаимодействие SwiftUI с вебом. Часть первая: WebView

Рутинная задача, без которой не обходится ни один проект – взаимодействие нативных приложений iOS со всемирной паутиной. В первой статье цикла разбираемся, как загружать веб-приложения в SwiftUI Views. СПОЙЛЕР: дальше будут рассмотрены боле…

31
Мар
2021

🎨 Создание дизайн-системы в Figma: практическое руководство

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

26
Мар
2021

🕸 gRPC и все-все-все: Часть I. Введение

Для лучшего понимания gRPC стоит разобраться и с другими протоколами. В первой части цикла мы поговорим о REST, RPC и затронем одну из его реализаций – SOAP.

Все сущее дв…

22
Мар
2021

🕸 Что такое HTTP и HTTPS?

Рассказываем о популярных протоколах, на которых построена всемирная паутина, а также отвечаем на вопросы новичков. Без понимания основ перейти к изучению более сложных тем не получится, а значит самое время восполнить пробелы в знаниях.

16
Мар
2021

🎨 Руководство для начинающих по созданию и анимации изображений SVG

Векторная графика помогает сделать дизайн сайта уникальным и масштабируемым. На примере простого значка мы расскажем о процессе создания и анимации изображений в популярном формате SVG.

Использование SVG для стилизации веб-сайтов открывает целый мир новых возможностей. Это отличный способ сделать дизайн уникальным и удобным для пользователей. Одно из самых больших преимуществ SVG – его гибкость и возможность изменять внутренние элементы изображения при помощи CSS. Вы можете создавать многоцветные значки и иллюстрации, а также анимировать их с помощью JavaScript или все того же CSS. SVG – векторный формат. Он масштабируется без потери качества, а правильно оптимизированная картинка мало весит. На примере небольшой иконки мы рассмотрим, как нужно работать с такими изображениями.

Создание SVG

Самый простой способ создать SVG – написать код:

        <svg width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="black" />
</svg>

    
Если вы хотите делать более сложные формы, лучше всего взять приложение для работы с векторной графикой, а затем экспортировать изображения в файлы SVG. Для этих целей, большинство разработчиков использует Adobe Illustrator или Sketch. Можно также отметить InkScape и онлайн-инструменты vectr.com или editor.method.ac.

Мы будем возьмем Illustrator. Как в любом приложении для работы с векторной графикой, большинство клиентских логотипов или иллюстраций представлены здесь в виде файлов AI, поэтому их можно легко открыть и экспортировать в SVG.

Для начала нужно создать новый веб-документ:


Размер холста – 400х400 пикселей. Размер на самом деле не имеет значения, потому что это вектор, но лучше оставить его в пределах, которые вы ожидаете увидеть в браузере. Будет легче поддерживать размер штриха и менять его, по сравнению с базовым. Далее создадим значок:


Важное практическое правило: чем меньше параметров, тем лучше! Так ваш код SVG будет чище и легче. Вы сделаете меньше ошибок, если не будете пытаться построить слишком сложные формы или рисованные иллюстрации.

При построении изображения можно использовать штрихи, различные цвета и даже градиенты. Все это будет экспортировано в SVG. Если вы планируете анимировать отдельные элементы значка, необходимо назвать слои и группы:


После экспорта имена будут преобразованы в идентификаторы: это будет полезно для более сложных иллюстраций. Лучше всего изменить идентификаторы на классы для внутренних элементов. Вы по-прежнему сможете использовать идентификатор для основного элемента <svg>, но им будет легче управлять, если пути и формы имеют классы.

Экспорт и оптимизация SVG-файлов

Когда значок будет готов, нужно экспортировать его в SVG. Для этого перейдите в: Файл -> Экспорт -> Экспортировать как.


Если вы хотите, чтобы холст SVG был того же же размера, что и монтажная область, или если вы экспортируете несколько значков из одного документа, установите флажок «Использовать монтажные области». В противном случае Illustrator обрежет холст до размера содержимого. Лучше всегда использовать размер артборда. Изображение будет легче поддерживать, если оно имеет определенный размер, особенно если нужно изменить или обновить иконку. Вы можете экспортировать его снова с тем же размером монтажной области.

Затем перед вами появится окно с параметрами для кода SVG:


В первом раскрывающемся списке необходимо выбрать способ создания CSS. Если у вас всего несколько элементов, лучше поставить «Inline style». Для более сложных иллюстраций есть «Internal CSS». Если вы не хотите использовать имена слоев и групп в качестве идентификаторов, измените раскрывающееся меню «Object IDs» на «Minimal». Это нужно для минимизации кода SVG перед отправкой в production. Если вы работаете над анимацией и хотите иметь более чистый код, снимите этот флажок.

После выбора опций экспортированный код значка выглядит примерно так:

        <svg id="my-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 290 290">
  <title>svg-icon</title>
  <circle id="circle" cx="145" cy="145" r="124.67" style="fill: none;stroke: #cfd8dc;stroke-miterlimit: 10;stroke-width: 20px"/>
  <polyline id="checkmark" points="88.75 148.26 124.09 183.6 201.37 106.32" style="fill: none;stroke: #21b587;stroke-linecap: round;stroke-linejoin: round;stroke-width: 25px"/>
</svg>

    

Теперь необходимо изменить идентификаторы внутренних элементов на классы и добавить некоторые атрибуты для лучшей доступности:

        <svg id="my-icon" aria-labelledby="svg-my-icon-title" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 290 290">
<title id="svg-my-icon-title">Checkmark Icon</title>
<circle class="circle" cx="145" cy="145" r="124.67" style="fill:none;stroke:#cfd8dc;stroke-miterlimit:10;stroke-width:20px"/>
<polyline class="checkmark" points="88.75 148.26 124.09 183.6 201.37 106.32" style="fill:none;stroke:#21b587;stroke-linecap:round;stroke-linejoin:round;stroke-width:25px"/>
</svg>

    

Файлы SVG не занимают много места, что может улучшить скорость загрузки страницы. Если вы хотите еще больше их оптимизировать, попробуйте отличный инструмент – SVGOMG.


Вы можете загрузить в него файл SVG и получить множество дополнительных опций его тонкой настройки. Будьте осторожны: если вы зайдете слишком далеко в настройке изображения, нарушите дизайн. Если у вас уже есть стили или анимация, убедитесь, что не потеряете после оптимизации классы и элементы.

Анимация и манипуляции с CSS

После добавления кода SVG на страницу, необходимо стилизовать его как и любой другой элемент HTML. Например так:

        #my-icon .circle {

  stroke: #21b587;

}
    

Вы без труда найдете множество библиотек JavaScript (Svg.js, SnapSVG) для создания сложных анимаций, однако в большинстве случаев добиться интересного эффекта можно, используя только свойства opacity, scale, translate и colors.

Далее создадим простую анимацию для круга:

         #my-icon .circle {
           	animation: circle-animation 0.5s ease-out forwards;
           	opacity: 0;
           	transform: scale(0.9);
           	transform-origin: center;
}
 
@keyframes circle-animation {
           	100% {
                           	opacity: 1;
                           	transform: scale(1);
           	}
}

    

Это простая масштабная анимация в сочетании с непрозрачностью. Если у вас есть несколько значков с похожим кругом, вы можете повторно использовать тот же код, что сэкономит много времени и усилий. Именно поэтому использование классов для отдельных элементов предпочтительнее уникальных идентификаторов.

Теперь посмотрим на анимацию значка галочки:

        #my-icon .checkmark {

            stroke-dasharray: 400;

            stroke-dashoffset: 400;

            stroke: #cfd8dc;

            transform-origin: center;

}

@keyframes checkmark-animation {

            40% {

                            transform: scale(1);

            }

            55% {

                            stroke: #cfd8dc;

                            transform: scale(1.2);

            }

            70% {

                            transform: scale(1);

            }

            100% {

                            stroke-dashoffset: 0;

                            transform: scale(1);

                            stroke: #21b587;

            }

}
   animation: checkmark-animation 1s ease-out forwards;
    

Дальше немного сложнее. Здесь мы используем stroke-dasharray и stroke-offset, чтобы создать эффект отрисовки значка. Подробнее этот метод описан в специальном руководстве. Также мы применяем масштабирование и меняем цвет обводки: как видите, код очень простой, но он дает довольно интересный эффект:

                    .icon-box {

                            padding: 100px;

                            position: relative;

                            width:200px;

            }

            .icon-box:before {

                            content: 'Hover to see animation.';

                            bottom: 5px;

                            display: block;

                            left: 0;

                            position: absolute;

                            text-align: center;

                            width: 100%;

            }

            .icon-box:hover .circle {

                            animation: circle-animation 0.5s ease-out forwards;

            }

            .icon-box:hover .checkmark {

                            animation: checkmark-animation 1s ease-out forwards;

                            animation-delay: 0.25s;

            }     

            #my-icon .circle {

                            opacity: 0;

                            transform: scale(0.9);

                            transform-origin: center;

            }

            #my-icon .checkmark {

                            stroke-dasharray: 400;

                            stroke-dashoffset: 400;

                            transform-origin: center;

                            stroke: #cfd8dc;

            }

            @keyframes circle-animation {

                            100% {

                                           opacity: 1;

                                           transform: scale(1);

                            }

            }

            @keyframes checkmark-animation {

                            40% {

                                           transform: scale(1);

                            }

                            55% {

                                           stroke: #cfd8dc;

                                           transform: scale(1.2);

                            }

                            70% {

                                           transform: scale(1);

                            }

                            100% {

                                           stroke-dashoffset: 0;

                                           transform: scale(1);

                                           stroke: #21b587;

                            }

            }
                        border: 1px solid #eee;
    
        <div class="icon-box">                                   	
<svg id="my-icon" aria-labelledby="svg-my-icon-title" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 290 290">
<title id="svg-my-icon-title">My Icon</title>
<circle class="circle" cx="145" cy="145" r="124.67" style="fill:none;stroke:#cfd8dc;stroke-miterlimit:10;stroke-width:20px"/>
<polyline class="checkmark" points="88.75 148.26 124.09 183.6 201.37 106.32" style="fill:none;stroke:#21b587;stroke-linecap:round;stroke-linejoin:round;stroke-width:25px"/>
</svg>
</div>

    

Результаты наших экспериментов можно увидеть здесь.

***

Мы привели очень простой пример, однако он показывает потенциал SVG для веб-проектов. Есть много разных способов использования популярного формата изображений и векторной анимации. Также существует неплохая спецификация этого, по сути, языка разметки XML и несколько справочников SVG-элементов и SVG-интерфейсов, с которыми читателям будет полезно ознакомиться.

Удачи вам в обучении и в создании красивых сайтов!

13
Мар
2021

🕵 Примеры атак XSS и способов их устранения

Понимание межсайтового скриптинга и способов борьбы с ним необходимо каждому веб-разработчику. Это один и самых распространенных видов уязвимостей – злоумышленники часто проводят атаки XSS для кражи данных и нарушения работоспособности сервисов.

Перевод публикуется с сокращениями, автор оригинальной статьи Russel Jones.

Межсайтовый
скриптинг (
XSS)
– это атака, которая позволяет
JavaScript через
один сайт работать с другим.
XSS интересен не из-за технической
сложности, а скорее потому, что он эксплуатирует некоторые из основных
механизмов безопасности браузеров и из-за огромной распространенности.

Background

Изначально Всемирная Паутина представляла собой набор статических документов HTML, которые браузер должен был отображать для просмотра пользователями. По мере развития Интернета возрастали и требования к документам, что привело к появлению JavaScript и файлов cookie: скрипты нужны для интерактивности документа, а cookies – чтобы браузеры могли сохранять его состояние.

Появление этих возможностей привело к тому, что браузеры не только визуализируют HTML,
но и вмещают в памяти в качестве API для разработчиков представление,
называемое объектной моделью документа (DOM). DOM предлагает древовидную структуру тегов HTML, а также доступ к файлам cookie для
получения состояния. Со временем модель превратилась из предназначенной преимущественно для чтения структуры в структуру read-write, обновление которой приводит к повторному рендерингу документа.

Как только документы
получили возможность запускать код, браузеры должны были определить контекст
выполнения для программ на JavaScript. Политика, которая была разработана, называется
Same-Origin и по-прежнему является одним из фундаментальных примитивов безопасности
браузера. Изначально в ней утверждалось, что JavaScript в одном документе может
получить доступ только к собственному DOM и к DOM других документов с тем же
происхождением. Позже, когда был добавлен XMLHttpRequest
и Fetch, появилась модифицированная версия
Same-Origin. Эти API не могут
выдавать запросы к любому источнику, они могут только читать ответ на запросы
от того же источника.

Что же такое происхождение? Это кортеж протокола, имени хоста и порта документа.

Фрагмент 1: Кортеж из схемы, хоста и порта этого URL-адреса.
        https://www.example.com:443/app
^^^^^   ^^^^^^^^^^^^^^^ ^^^
Scheme  Host            Port
    
Рис. 1: Иллюстрация Same-Origin в действии. JavaScript работает на www.evil.com и не может получить доступ к DOM на www.example.com.
Рис. 1: Иллюстрация Same-Origin в действии. JavaScript работает на www.evil.com и не может получить доступ к DOM на www.example.com.

Политика Same-Origin
отлично помогает смягчать атаки на статические сайты, как показано на рисунке выше.
Однако с атаками на динамические ресурсы, принимающие пользовательский ввод, ситуация
немного сложнее из-за смешивания кода и данных, которая позволяет злоумышленнику
выполнять контролируемый ввод в исходном документе.

Атаки XSS обычно бывают трех видов: рефлективными, хранимыми и основанными на DOM.

Рефлективные и хранимые
XSS-атаки принципиально одинаковы, поскольку полагаются на вредоносный ввод,
отправляемый на бекенд и представляющий этот ввод пользователю сервер.
Рефлективные XSS обычно возникают в виде злонамеренно созданной злоумышленником
ссылки, по которой затем переходит жертва. Хранимые XSS происходят, когда
злоумышленник загружает вредоносный ввод. Атаки на основе DOM отличаются тем,
что они происходят исключительно на стороне клиента и включают вредоносный ввод, манипулирующий DOM.

Примеры

Рефлективные атаки XSS

Ниже можно увидеть
простое веб-приложение на Go, которое отражает свой ввод (даже если
это вредоносный скрипт) обратно пользователю. Вы можете использовать это
приложение, сохранив его в файле xss1.go и запустив go run xss1.go.

Фрагмент 3: Пример веб-приложения с рефлективной (отраженной) XSS-атакой.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")

    messages, ok := r.URL.Query()["message"]
    if !ok {
       messages = []string{"hello, world"}
    }
    fmt.Fprintf(w, "<html><p>%v</p></html>", messages[0])
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть
XSS-атаку, перейдите по уязвимому URL-адресу ниже.

        http://localhost:8080?message=<script>alert(1)</script>
    

Взгляните на источник: сервер вернул документ, который выглядит примерно так, как показано во фрагменте
4. Обратите внимание, как смешение кода и данных позволило произойти этой
атаке.

Фрагмент 4: Пример вывода уязвимого для XSS веб-приложения.
        <html>
  <p>
    <script>alert(1)</script>
  </p>
</html>
    

Этот пример может
показаться неправдоподобным, поскольку защита XSS была явно отключена. Эта ее форма основана на эвристике с обходными путями для
различных браузеров. Она была отключена для создания кроссбраузерных примеров,
иллюстрирующих основные концепции XSS-атак. Некоторые браузеры
удаляют эту защиту: например, в
Google Chrome 78
и выше вам не понадобится строка
w.Header().Set(“X-XSS-Protection”, “0”), чтобы атака сработала.

Хранимые XSS-атаки

Хранимые XSS-атаки похожи на рефлективные, но пэйлоад поступает из хранилища данных, а не из ввода непосредственно. Например, злоумышленник может загрузить в веб-приложение зловреда, который затем будет показан каждому авторизованному юзеру.

Ниже приведен простой чат, который иллюстрирует этот вид атак. Вы можете сохранить приложение в файле xss2.go и
запустить с помощью команды go run xss2.go.

Фрагмент 5: Хранимая XSS-атака.
        package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
)

var db []string
var mu sync.Mutex

var tmpl = `
<form action="/save">
  Message: <input name="message" type="text"><br>
  <input type="submit" value="Submit">
</form>
%v
`

func saveHandler(w http.ResponseWriter, r *http.Request) {
	mu.Lock()
	defer mu.Unlock()

	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	db = append(db, messages[0])

	http.Redirect(w, r, "/", 301)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	var sb strings.Builder
	sb.WriteString("<ul>")
	for _, message := range db {
		sb.WriteString("<li>" + message + "</li>")
	}
	sb.WriteString("</ul>")

	fmt.Fprintf(w, tmpl, sb.String())
}

func main() {
	http.HandleFunc("/", viewHandler)
	http.HandleFunc("/save", saveHandler)
	log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть атаку
XSS, перейдите по ссылке http://localhost:8080 и введите сообщение <script>alert(1);</script>.

Атака делится на две
фазы:

  • пейлоад сохраняется в хранилище данных в функции storeHandler;
  • когда страница визуализируется во ViewHandler, пейлоад добавляется к выходным данным.

XSS-атаки на основе DOM

Такие атаки не связаны с бекендом и происходят исключительно на стороне клиента. Они интересны тем, что современные веб-приложения перемещают логику к клиенту, а атаки происходят, когда пользователь напрямую манипулирует DOM. Хорошей новостью для злоумышленников является то, что DOM имеет широкий спектр способов эксплуатации, наиболее популярными из которых являются innerHTML и document.write.

Ниже приведен пример обслуживающего статический контент веб-приложения. Код тот же, что и в
примере с рефлективными XSS, но здесь атака будет происходить полностью на
стороне клиента. Вы можете сохранить приложение в файле xss3.go и запустить его командой go run xss3.go.

Фрагмент 6: Пример веб-приложения с XSS-атакой на основе DOM.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

const content = `

<html>
   <head>
       <script>
          window.onload = function() {
             var params = new URLSearchParams(window.location.search);
             p = document.getElementById("content")
             p.innerHTML = params.get("message")
	     };
       </script>
   </head>
   <body>
       <p id="content"></p>
   </body>
</html>
`

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")
    fmt.Fprintf(w, content)
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть эту
атаку, перейдите по ссылке
http://localhost:8080/?message=”<img src=1 onerror=alert(1);/>”. Обратите внимание, что вектор атаки немного
отличается и innerHTML не будет
выполнять скрипт напрямую, однако он добавит HTML-элементы, которые затем выполнят код на JavaScript. В приведенном примере добавляется элемент image, который запускает скрипт при возникновении ошибки (она всегда появляется, поскольку злоумышленник подставляет неверный источник).

Если хотите напрямую добавить
элемент скрипта, придется использовать другой приемник XSS. Замените
элемент script из фрагмента 6 элементом script из фрагмента 7 и перейдите
по следующей ссылке:
http://localhost:8080/?message=”<script>alert(1);</script>”. Атака сработает, потому что document.write принимает элементы
скрипта напрямую.

Фрагмент 7: Еще один пример атаки XSS на основе DOM.
        <script>
   window.onload = function() {
      var params = new URLSearchParams(window.location.search);
      document.open();
      document.write(params.get("message"));
      document.close();
   };
</script>
    

Связанные направления атак

Хотя обычно их не называют атаками XSS, существует несколько связанных направлений, о которых стоит упомянуть.

Content-type

Всему виной
неправильная настройка типа содержимого ответов HTTP. Это может произойти как
на уровне бекенда (ответ имеет неверный набор заголовков Content-Type), так и при попытке браузера проснифферить тип MIME.
Internet Explorer был особенно восприимчив к этому, и классическим примером
является служба загрузки изображений: злоумышленник может загрузить JavaScript вместо картинки.
Браузер видит, что тип контента был установлен на image/jpg, но пейлоад содержит скрипт – он выполняется, что приводит к атаке XSS.

Urlschemes

Следующий тип атаки –
активность через URL со схемой JavaScript. Представим веб-сайт, который
позволяет пользователю контролировать цель ссылки, как показано во фрагменте 8. В этом случае злоумышленник сможет предоставить
URL, выполняющий некий JavaScript с помощью нашей схемы.

Чтобы опробовать этот
тип атаки, можно сохранить приложение в файле xss4.go, запустить командой go run xss4.go и перейти по ссылке http://localhost:8080?link=javascript:alert(1).

Фрагмент 8: XSS-атака, введенная через схему URL-адресов.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")

    links, ok := r.URL.Query()["link"]
    if !ok {
        messages = []string{"example.com"}
    }
    fmt.Fprintf(w, `<html><p><a href="%v">Next</p></html>`, links[0])
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Избавление

Единого метода
решения данной проблемы не существует, иначе XSS не был бы
такой распространенной проблемой. Фундаментальная сложность вызвана отсутствием разделения между кодом и данными. Смягчение последствий XSS
обычно включает очистку входных данных (нужно убедиться, что они не
содержат кода), экранирование выходных данных (они также не должны содержать код) и реструктуризацию приложения таким образом, чтобы код
загружался из строго определенных конечных точек.

Валидация входных данных

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

Валидация
данных – сложная проблема. Не существует универсального инструмента или техники
для всех ситуаций. Лучше всего структурировать приложение таким образом, чтобы
оно требовало от разработчиков продумать тип принимаемых данных и обеспечить
удобное место, где можно разместить валидатор.

Хороший тон написания
приложений на Go состоит в том, чтобы не иметь никакой логики приложения в
обработчиках запросов HTTP, а вместо этого использовать их для анализа и проверки входных данных. Затем данные отправляются
в
обрабатывающую логику структуру. Обработчики запросов становятся
простыми и обеспечивают удобное централизованное расположение для контроля
правильности очистки данных.

На фрагменте 9
показано, как можно переписать saveHandler для приема символов ASCII [A-Za-z\.].

Фрагмент 9: Пример использования обработчиков HTTP-запросов для проверки данных.
        func saveHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	re := regexp.MustCompile(`^[A-Za-z\\.]+$`)
	if re.Find([]byte(messages[0]))) == "" {
		http.Error(w, "invalid message", 500)
	}
  
	db.Append(messages[0])

	http.Redirect(w, r, "/", 301)
}
    

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

Экранирование

Следующий шаг – экранирование вывода. В случае с нашим чатом все извлеченное из базы данных включалось непосредственно в выходной документ.

Одно и то же приложение
может быть гораздо безопаснее (даже если в него была произведена инъекция кода),
если экранировать все небезопасные выходные данные. Именно это делает пакет
html/template в Go. Использование языка шаблонов и
контекстно-зависимого синтаксического анализатора для экранирования данных до
их визуализации уменьшит вероятность выполнения вредоносного кода.

Ниже приведен пример
использования пакета html/template. Сохраните приложение в файле xss5.go, а затем выполните командой go run xss5.go.

Фрагмент 10: Использование экранирования для устранения хранимых XSS-атак.
        package main

import (
	"bytes"
	"html/template"
	"io"
	"log"
	"net/http"
	"sync"
)

var db []string
var mu sync.Mutex

var tmpl = `
<form action="/save">
  Message: <input name="message" type="text"><br>
  <input type="submit" value="Submit">
</form>
<ul>
{{range .}}
    <li>{{.}}</li>
{{end}}
</ul>`

func saveHandler(w http.ResponseWriter, r *http.Request) {
	mu.Lock()
	defer mu.Unlock()

	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	db = append(db, messages[0])

	http.Redirect(w, r, "/", 301)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	t := template.New("view")

	t, err := t.Parse(tmpl)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var buf bytes.Buffer

	err = t.Execute(&buf, db)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	io.Copy(w, &buf)
}

func main() {
	http.HandleFunc("/", viewHandler)
	http.HandleFunc("/save", saveHandler)
	log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Опробуйте использованную ранее атаку XSS, перейдя по ссылке http://localhost:8080 и введите <script>alert(1);</script>.
Обратите внимание, что предупреждение не было вызвано.

Откройте консоль браузера и посмотрите на элемент li в DOM. Интерес представляют два
свойства: innerHTML и innerText.

Фрагмент 11: Проверка DOM при использовании экранирования.
        innerHTML: "<script>alert(1);</script>"
innerText: "<script>alert(1);</script>"
    

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

Content Security Policy

Content Security Policy (CSP) позволяет веб-приложениям определять набор доверенных источников для загрузки контента (например, скриптов). CSP можно использовать для разделения кода и данных, отказываясь от встроенных скриптов и загружая их только из определенных источников.

Написание CSP для
небольших автономных приложений является простой задачей – начните с политики,
которая по умолчанию запрещает все источники, а затем разрешите небольшой их набор.
Однако написать эффективный CSP для больших сайтов уже не так просто. Как
только сайт начинает загружать контент из внешних источников, CSP раздувается и
становится громоздким. Некоторые разработчики сдаются и включают директиву unsafe-inline, полностью разрушая теорию
CSP.

Чтобы упростить
написание CSP, в CSP3 вводится директива strict-dynamic.
Вместо того чтобы поддерживать большой белый список надежных источников,
приложение генерирует случайное число (nonce) каждый раз, когда запрашивается
страница. Этот nonce отправляется вместе с заголовками страницы и встроен в тег
script, что заставляет браузеры доверять этим скриптам с соответствующим nonce,
а также любым скриптам, которые они могут загрузить. Вместо
того, чтобы вносить скрипты в белый список и пытаться выяснить, какие еще сценарии они загружают, а затем пополнять белый список рекурсивно,
вам нужно достаточно внести в белый список импортируемый скрипт верхнего уровня.

Используя предложенный Google подход Strict CSP, рассмотрим простое приложение, принимающее
пользовательский ввод. Сохраните его в файле xss6.go, а затем выполните командой go run xss6.go.

Фрагмент 12: Пример CSP, смягчающего XSS-атаку.
        package main

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strings"
)

const scriptContent = `
document.addEventListener('DOMContentLoaded', function () {
   var updateButton = document.getElementById("textUpdate");
   updateButton.addEventListener("click", function() {
      var p = document.getElementById("content");
      var message = document.getElementById("textInput").value;
      p.innerHTML = message;
   });
};
`

const htmlContent = `
<html>
   <head>
      <script src="script.js" nonce="{{ . }}"></script>
   </head>
   <body>
       <p id="content"></p>

       <div class="input-group mb-3">
         <input type="text" class="form-control" id="textInput">
         <div class="input-group-append">
           <button class="btn btn-outline-secondary" type="button" id="textUpdate">Update</button>
         </div>
       </div>

       <blockquote class="twitter-tweet" data-lang="en">
         <a href="https://twitter.com/jack/status/20?ref_src=twsrc%5Etfw">March 21, 2006</a>
       </blockquote>
       <script async src="https://platform.twitter.com/widgets.js"
         nonce="{{ . }}" charset="utf-8"></script>
   </body>
</html>
`

func generateNonce() (string, error) {
	buf := make([]byte, 16)
	_, err := rand.Read(buf)
	if err != nil {
		return "", err
	}

	return base64.StdEncoding.EncodeToString(buf), nil
}

func generateHTML(nonce string) (string, error) {
	var buf bytes.Buffer

	t, err := template.New("htmlContent").Parse(htmlContent)
	if err != nil {
		return "", err
	}

	err = t.Execute(&buf, nonce)
	if err != nil {
		return "", err
	}

	return buf.String(), nil
}

func generatePolicy(nonce string) string {
	s := fmt.Sprintf(`'nonce-%v`, nonce) 
	var contentSecurityPolicy = []string{
		`object-src 'none';`,
		fmt.Sprintf(`script-src %v 'strict-dynamic';`, s),
		`base-uri 'none';`,
	}
	return strings.Join(contentSecurityPolicy, " ")
}

func scriptHandler(w http.ResponseWriter, r *http.Request) {
	nonce, err := generateNonce()
	if err != nil {
		returnError()
		return
	}

	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
	w.Header().Set("Content-Security-Policy", generatePolicy(nonce))

	fmt.Fprintf(w, scriptContent)
}

func htmlHandler(w http.ResponseWriter, r *http.Request) {
	nonce, err := generateNonce()
	if err != nil {
		returnError()
		return
	}

	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Header().Set("Content-Security-Policy", generatePolicy(nonce))

	htmlContent, err := generateHTML(nonce)
	if err != nil {
returnError()
		return
	}

	fmt.Fprintf(w, htmlContent)
}

func returnError() {
http.Error(w, http.StatusText(http.StatusInternalServerError),
		http.StatusInternalServerError)
}

func main() {
	http.HandleFunc("/script.js", scriptHandler)
	http.HandleFunc("/", htmlHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
    

Чтобы попытаться
использовать приложение, перейдите по ссылке: http://localhost:8080 и
попробуйте отправить <img src=1 onerror”alert(1)”/> как и раньше. Эта атака сработала бы и без CSP, но
поскольку CSP не допускает inline-скриптов, вы должны увидеть примерно такой вывод в консоли браузера:

«Отказано в выполнении встроенного обработчика событий, поскольку он нарушает следующую директиву CSP: “script-src ‘nonce-XauzABRw9QtE0bzoiRmslQ==’ ‘unsafe-inline’ ‘unsafe-eval’ ‘strict-dynamic’ https: http:” Обратите внимание, что ‘unsafe-inline‘ игнорируется, если в исходном списке присутствует либо хэш, либо значение nonce.»

Почему сценарий не
запустился? Рассмотрим
CSP подробнее.

Фрагмент 13: Базовый CSP. Nonce повторно генерируется для каждого запроса.
        script-src 'strict-dynamic' 'nonce-XauzABRw9QtE0bzoiRmslQ==';
object-src 'none';
base-uri 'none';
    
Что делает эта политика? Директива script-src включает strict-dynamic и значение nonce, используемое для загрузки скриптов. Это означает, что единственные скрипты, которые будут загружены, находятся в script elements, где nonce включен в атрибут, а значит inline-скрипты не загрузятся. Последние две директивы препятствуют загрузке плагинов и изменению базового URL приложения.

Основная сложность
использования этого подхода заключается в необходимости генерировать nonce и инжектить его в заголовки при каждой загрузке страницы. После этого шаблон
может быть применен ко всем загружаемым страницам.

Соответствующие методы устранения

Content-Type

Вы
должны не только устанавливать свой Content-Type, но и следить, чтобы браузеры не
пытались автоматически определить тип контента. Для
этого используйте заголовок: X-Content-Type-Options:
nosniff
.

Virtual doms

Хотя виртуальные домены
не являются функцией безопасности, использующие их современные фреймворки (
React и Vue) могут помочь смягчить атаки XSS на основе DOM.

Эти фреймворки создают DOM параллельно с тем, который находится в браузере, и сравнивают их. Отличающуюся часть DOM браузера они обновляют. Для этого необходимо создать виртуальный DOM, что приведет к уменьшению использования клиентами innerHTML и подтолкнет разработчиков к переходу на innerText.

React требует
использования атрибута
dangerouslySetInnerHTML, в то время как создатели Vue предупреждают, что использование
innerHTML может привести к появлению уязвимостей.

Заключение

Если вы дочитали до
конца, у вас может появиться желание разобраться, как работают браузеры, что такое ошибки
XSS и насколько важно понимать, как от них избавиться.
XSS трудно искоренить, поскольку приложения становятся все больше и все сложнее. Применяя упомянутые в статье методы, можно сделать жизнь злоумышленников трудной.

Удачи в борьбе и учебе!

Дополнительные материалы:

13
Мар
2021

🕵 Примеры атак XSS и способов их ослабления

Понимание межсайтового скриптинга и способов борьбы с ним необходимо каждому веб-разработчику. Это один из самых распространенных видов уязвимостей – злоумышленники часто проводят атаки XSS для кражи данных и нарушения работоспособности сервисов.

Перевод публикуется с сокращениями, автор оригинальной статьи Russel Jones.

Межсайтовый
скриптинг (
XSS)
– это атака, которая позволяет
JavaScript через
один сайт работать с другим.
XSS интересен не из-за технической
сложности, а скорее потому, что он эксплуатирует некоторые из основных
механизмов безопасности браузеров и из-за огромной распространенности.

Background

Изначально Всемирная Паутина представляла собой набор статических документов HTML, которые браузер должен был отображать для просмотра пользователями. По мере развития Интернета возрастали и требования к документам, что привело к появлению JavaScript и файлов cookie: скрипты нужны для интерактивности документа, а cookies – чтобы браузеры могли сохранять его состояние.

Появление этих возможностей привело к тому, что браузеры не только визуализируют HTML,
но и вмещают в памяти в качестве API для разработчиков представление,
называемое объектной моделью документа (DOM). DOM предлагает древовидную структуру тегов HTML, а также доступ к файлам cookie для
получения состояния. Со временем модель превратилась из предназначенной преимущественно для чтения структуры в структуру read-write, обновление которой приводит к повторному рендерингу документа.

Как только документы
получили возможность запускать код, браузеры должны были определить контекст
выполнения для программ на JavaScript. Политика, которая была разработана, называется
Same-Origin и по-прежнему является одним из фундаментальных примитивов безопасности
браузера. Изначально в ней утверждалось, что JavaScript в одном документе может
получить доступ только к собственному DOM и к DOM других документов с тем же
происхождением. Позже, когда был добавлен XMLHttpRequest
и Fetch, появилась модифицированная версия
Same-Origin. Эти API не могут
выдавать запросы к любому источнику, они могут только читать ответ на запросы
от того же источника.

Что же такое происхождение? Это кортеж протокола, имени хоста и порта документа.

Фрагмент 1: Кортеж из схемы, хоста и порта этого URL-адреса.
        https://www.example.com:443/app
^^^^^   ^^^^^^^^^^^^^^^ ^^^
Scheme  Host            Port
    
Рис. 1: Иллюстрация Same-Origin в действии. JavaScript работает на www.evil.com и не может получить доступ к DOM на www.example.com.
Рис. 1: Иллюстрация Same-Origin в действии. JavaScript работает на www.evil.com и не может получить доступ к DOM на www.example.com.

Политика Same-Origin
отлично помогает смягчать атаки на статические сайты, как показано на рисунке выше.
Однако с атаками на динамические ресурсы, принимающие пользовательский ввод, ситуация
немного сложнее из-за смешивания кода и данных, которая позволяет злоумышленнику
выполнять контролируемый ввод в исходном документе.

Атаки XSS обычно бывают трех видов: рефлективными, хранимыми и основанными на DOM.

Рефлективные и хранимые
XSS-атаки принципиально одинаковы, поскольку полагаются на вредоносный ввод,
отправляемый на бекенд и представляющий этот ввод пользователю сервер.
Рефлективные XSS обычно возникают в виде злонамеренно созданной злоумышленником
ссылки, по которой затем переходит жертва. Хранимые XSS происходят, когда
злоумышленник загружает вредоносный ввод. Атаки на основе DOM отличаются тем,
что они происходят исключительно на стороне клиента и включают вредоносный ввод, манипулирующий DOM.

Примеры

Рефлективные атаки XSS

Ниже можно увидеть
простое веб-приложение на Go, которое отражает свой ввод (даже если
это вредоносный скрипт) обратно пользователю. Вы можете использовать это
приложение, сохранив его в файле xss1.go и запустив go run xss1.go.

Фрагмент 3: Пример веб-приложения с рефлективной (отраженной) XSS-атакой.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")

    messages, ok := r.URL.Query()["message"]
    if !ok {
       messages = []string{"hello, world"}
    }
    fmt.Fprintf(w, "<html><p>%v</p></html>", messages[0])
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть
XSS-атаку, перейдите по уязвимому URL-адресу ниже.

        http://localhost:8080?message=<script>alert(1)</script>
    

Взгляните на источник: сервер вернул документ, который выглядит примерно так, как показано во фрагменте
4. Обратите внимание, как смешение кода и данных позволило произойти этой
атаке.

Фрагмент 4: Пример вывода уязвимого для XSS веб-приложения.
        <html>
  <p>
    <script>alert(1)</script>
  </p>
</html>
    

Этот пример может
показаться неправдоподобным, поскольку защита XSS была явно отключена. Эта ее форма основана на эвристике с обходными путями для
различных браузеров. Она была отключена для создания кроссбраузерных примеров,
иллюстрирующих основные концепции XSS-атак. Некоторые браузеры
удаляют эту защиту: например, в
Google Chrome 78
и выше вам не понадобится строка
w.Header().Set(“X-XSS-Protection”, “0”), чтобы атака сработала.

Хранимые XSS-атаки

Хранимые XSS-атаки похожи на рефлективные, но пэйлоад поступает из хранилища данных, а не из ввода непосредственно. Например, злоумышленник может загрузить в веб-приложение зловреда, который затем будет показан каждому авторизованному юзеру.

Ниже приведен простой чат, который иллюстрирует этот вид атак. Вы можете сохранить приложение в файле xss2.go и
запустить с помощью команды go run xss2.go.

Фрагмент 5: Хранимая XSS-атака.
        package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
)

var db []string
var mu sync.Mutex

var tmpl = `
<form action="/save">
  Message: <input name="message" type="text"><br>
  <input type="submit" value="Submit">
</form>
%v
`

func saveHandler(w http.ResponseWriter, r *http.Request) {
	mu.Lock()
	defer mu.Unlock()

	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	db = append(db, messages[0])

	http.Redirect(w, r, "/", 301)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	var sb strings.Builder
	sb.WriteString("<ul>")
	for _, message := range db {
		sb.WriteString("<li>" + message + "</li>")
	}
	sb.WriteString("</ul>")

	fmt.Fprintf(w, tmpl, sb.String())
}

func main() {
	http.HandleFunc("/", viewHandler)
	http.HandleFunc("/save", saveHandler)
	log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть атаку
XSS, перейдите по ссылке http://localhost:8080 и введите сообщение <script>alert(1);</script>.

Атака делится на две
фазы:

  • пейлоад сохраняется в хранилище данных в функции storeHandler;
  • когда страница визуализируется во ViewHandler, пейлоад добавляется к выходным данным.

XSS-атаки на основе DOM

Такие атаки не связаны с бекендом и происходят исключительно на стороне клиента. Они интересны тем, что современные веб-приложения перемещают логику к клиенту, а атаки происходят, когда пользователь напрямую манипулирует DOM. Хорошей новостью для злоумышленников является то, что DOM имеет широкий спектр способов эксплуатации, наиболее популярными из которых являются innerHTML и document.write.

Ниже приведен пример обслуживающего статический контент веб-приложения. Код тот же, что и в
примере с рефлективными XSS, но здесь атака будет происходить полностью на
стороне клиента. Вы можете сохранить приложение в файле xss3.go и запустить его командой go run xss3.go.

Фрагмент 6: Пример веб-приложения с XSS-атакой на основе DOM.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

const content = `

<html>
   <head>
       <script>
          window.onload = function() {
             var params = new URLSearchParams(window.location.search);
             p = document.getElementById("content")
             p.innerHTML = params.get("message")
	     };
       </script>
   </head>
   <body>
       <p id="content"></p>
   </body>
</html>
`

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")
    fmt.Fprintf(w, content)
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Чтобы увидеть эту
атаку, перейдите по ссылке
http://localhost:8080/?message=”<img src=1 onerror=alert(1);/>”. Обратите внимание, что вектор атаки немного
отличается и innerHTML не будет
выполнять скрипт напрямую, однако он добавит HTML-элементы, которые затем выполнят код на JavaScript. В приведенном примере добавляется элемент image, который запускает скрипт при возникновении ошибки (она всегда появляется, поскольку злоумышленник подставляет неверный источник).

Если хотите напрямую добавить
элемент скрипта, придется использовать другой приемник XSS. Замените
элемент script из фрагмента 6 элементом script из фрагмента 7 и перейдите
по следующей ссылке:
http://localhost:8080/?message=”<script>alert(1);</script>”. Атака сработает, потому что document.write принимает элементы
скрипта напрямую.

Фрагмент 7: Еще один пример атаки XSS на основе DOM.
        <script>
   window.onload = function() {
      var params = new URLSearchParams(window.location.search);
      document.open();
      document.write(params.get("message"));
      document.close();
   };
</script>
    

Связанные направления атак

Хотя обычно их не называют атаками XSS, существует несколько связанных направлений, о которых стоит упомянуть.

Content-type

Всему виной
неправильная настройка типа содержимого ответов HTTP. Это может произойти как
на уровне бекенда (ответ имеет неверный набор заголовков Content-Type), так и при попытке браузера проснифферить тип MIME.
Internet Explorer был особенно восприимчив к этому, и классическим примером
является служба загрузки изображений: злоумышленник может загрузить JavaScript вместо картинки.
Браузер видит, что тип контента был установлен на image/jpg, но пейлоад содержит скрипт – он выполняется, что приводит к атаке XSS.

Urlschemes

Следующий тип атаки –
активность через URL со схемой JavaScript. Представим веб-сайт, который
позволяет пользователю контролировать цель ссылки, как показано во фрагменте 8. В этом случае злоумышленник сможет предоставить
URL, выполняющий некий JavaScript с помощью нашей схемы.

Чтобы опробовать этот
тип атаки, можно сохранить приложение в файле xss4.go, запустить командой go run xss4.go и перейти по ссылке http://localhost:8080?link=javascript:alert(1).

Фрагмент 8: XSS-атака, введенная через схему URL-адресов.
        package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-XSS-Protection", "0")

    links, ok := r.URL.Query()["link"]
    if !ok {
        messages = []string{"example.com"}
    }
    fmt.Fprintf(w, `<html><p><a href="%v">Next</p></html>`, links[0])
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Избавление

Единого метода
решения данной проблемы не существует, иначе XSS не был бы
такой распространенной проблемой. Фундаментальная сложность вызвана отсутствием разделения между кодом и данными. Смягчение последствий XSS
обычно включает очистку входных данных (нужно убедиться, что они не
содержат кода), экранирование выходных данных (они также не должны содержать код) и реструктуризацию приложения таким образом, чтобы код
загружался из строго определенных конечных точек.

Валидация входных данных

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

Валидация
данных – сложная проблема. Не существует универсального инструмента или техники
для всех ситуаций. Лучше всего структурировать приложение таким образом, чтобы
оно требовало от разработчиков продумать тип принимаемых данных и обеспечить
удобное место, где можно разместить валидатор.

Хороший тон написания
приложений на Go состоит в том, чтобы не иметь никакой логики приложения в
обработчиках запросов HTTP, а вместо этого использовать их для анализа и проверки входных данных. Затем данные отправляются
в
обрабатывающую логику структуру. Обработчики запросов становятся
простыми и обеспечивают удобное централизованное расположение для контроля
правильности очистки данных.

На фрагменте 9
показано, как можно переписать saveHandler для приема символов ASCII [A-Za-z\.].

Фрагмент 9: Пример использования обработчиков HTTP-запросов для проверки данных.
        func saveHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	re := regexp.MustCompile(`^[A-Za-z\\.]+$`)
	if re.Find([]byte(messages[0]))) == "" {
		http.Error(w, "invalid message", 500)
	}
  
	db.Append(messages[0])

	http.Redirect(w, r, "/", 301)
}
    

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

Экранирование

Следующий шаг – экранирование вывода. В случае с нашим чатом все извлеченное из базы данных включалось непосредственно в выходной документ.

Одно и то же приложение
может быть гораздо безопаснее (даже если в него была произведена инъекция кода),
если экранировать все небезопасные выходные данные. Именно это делает пакет
html/template в Go. Использование языка шаблонов и
контекстно-зависимого синтаксического анализатора для экранирования данных до
их визуализации уменьшит вероятность выполнения вредоносного кода.

Ниже приведен пример
использования пакета html/template. Сохраните приложение в файле xss5.go, а затем выполните командой go run xss5.go.

Фрагмент 10: Использование экранирования для устранения хранимых XSS-атак.
        package main

import (
	"bytes"
	"html/template"
	"io"
	"log"
	"net/http"
	"sync"
)

var db []string
var mu sync.Mutex

var tmpl = `
<form action="/save">
  Message: <input name="message" type="text"><br>
  <input type="submit" value="Submit">
</form>
<ul>
{{range .}}
    <li>{{.}}</li>
{{end}}
</ul>`

func saveHandler(w http.ResponseWriter, r *http.Request) {
	mu.Lock()
	defer mu.Unlock()

	r.ParseForm()
	messages, ok := r.Form["message"]
	if !ok {
		http.Error(w, "missing message", 500)
	}

	db = append(db, messages[0])

	http.Redirect(w, r, "/", 301)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	t := template.New("view")

	t, err := t.Parse(tmpl)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	var buf bytes.Buffer

	err = t.Execute(&buf, db)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	io.Copy(w, &buf)
}

func main() {
	http.HandleFunc("/", viewHandler)
	http.HandleFunc("/save", saveHandler)
	log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
    

Опробуйте использованную ранее атаку XSS, перейдя по ссылке http://localhost:8080 и введите <script>alert(1);</script>.
Обратите внимание, что предупреждение не было вызвано.

Откройте консоль браузера и посмотрите на элемент li в DOM. Интерес представляют два
свойства: innerHTML и innerText.

Фрагмент 11: Проверка DOM при использовании экранирования.
        innerHTML: "<script>alert(1);</script>"
innerText: "<script>alert(1);</script>"
    

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

Content Security Policy

Content Security Policy (CSP) позволяет веб-приложениям определять набор доверенных источников для загрузки контента (например, скриптов). CSP можно использовать для разделения кода и данных, отказываясь от встроенных скриптов и загружая их только из определенных источников.

Написание CSP для
небольших автономных приложений является простой задачей – начните с политики,
которая по умолчанию запрещает все источники, а затем разрешите небольшой их набор.
Однако написать эффективный CSP для больших сайтов уже не так просто. Как
только сайт начинает загружать контент из внешних источников, CSP раздувается и
становится громоздким. Некоторые разработчики сдаются и включают директиву unsafe-inline, полностью разрушая теорию
CSP.

Чтобы упростить
написание CSP, в CSP3 вводится директива strict-dynamic.
Вместо того чтобы поддерживать большой белый список надежных источников,
приложение генерирует случайное число (nonce) каждый раз, когда запрашивается
страница. Этот nonce отправляется вместе с заголовками страницы и встроен в тег
script, что заставляет браузеры доверять этим скриптам с соответствующим nonce,
а также любым скриптам, которые они могут загрузить. Вместо
того, чтобы вносить скрипты в белый список и пытаться выяснить, какие еще сценарии они загружают, а затем пополнять белый список рекурсивно,
вам нужно достаточно внести в белый список импортируемый скрипт верхнего уровня.

Используя предложенный Google подход Strict CSP, рассмотрим простое приложение, принимающее
пользовательский ввод. Сохраните его в файле xss6.go, а затем выполните командой go run xss6.go.

Фрагмент 12: Пример CSP, смягчающего XSS-атаку.
        package main

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strings"
)

const scriptContent = `
document.addEventListener('DOMContentLoaded', function () {
   var updateButton = document.getElementById("textUpdate");
   updateButton.addEventListener("click", function() {
      var p = document.getElementById("content");
      var message = document.getElementById("textInput").value;
      p.innerHTML = message;
   });
};
`

const htmlContent = `
<html>
   <head>
      <script src="script.js" nonce="{{ . }}"></script>
   </head>
   <body>
       <p id="content"></p>

       <div class="input-group mb-3">
         <input type="text" class="form-control" id="textInput">
         <div class="input-group-append">
           <button class="btn btn-outline-secondary" type="button" id="textUpdate">Update</button>
         </div>
       </div>

       <blockquote class="twitter-tweet" data-lang="en">
         <a href="https://twitter.com/jack/status/20?ref_src=twsrc%5Etfw">March 21, 2006</a>
       </blockquote>
       <script async src="https://platform.twitter.com/widgets.js"
         nonce="{{ . }}" charset="utf-8"></script>
   </body>
</html>
`

func generateNonce() (string, error) {
	buf := make([]byte, 16)
	_, err := rand.Read(buf)
	if err != nil {
		return "", err
	}

	return base64.StdEncoding.EncodeToString(buf), nil
}

func generateHTML(nonce string) (string, error) {
	var buf bytes.Buffer

	t, err := template.New("htmlContent").Parse(htmlContent)
	if err != nil {
		return "", err
	}

	err = t.Execute(&buf, nonce)
	if err != nil {
		return "", err
	}

	return buf.String(), nil
}

func generatePolicy(nonce string) string {
	s := fmt.Sprintf(`'nonce-%v`, nonce) 
	var contentSecurityPolicy = []string{
		`object-src 'none';`,
		fmt.Sprintf(`script-src %v 'strict-dynamic';`, s),
		`base-uri 'none';`,
	}
	return strings.Join(contentSecurityPolicy, " ")
}

func scriptHandler(w http.ResponseWriter, r *http.Request) {
	nonce, err := generateNonce()
	if err != nil {
		returnError()
		return
	}

	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
	w.Header().Set("Content-Security-Policy", generatePolicy(nonce))

	fmt.Fprintf(w, scriptContent)
}

func htmlHandler(w http.ResponseWriter, r *http.Request) {
	nonce, err := generateNonce()
	if err != nil {
		returnError()
		return
	}

	w.Header().Set("X-XSS-Protection", "0")
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Header().Set("Content-Security-Policy", generatePolicy(nonce))

	htmlContent, err := generateHTML(nonce)
	if err != nil {
returnError()
		return
	}

	fmt.Fprintf(w, htmlContent)
}

func returnError() {
http.Error(w, http.StatusText(http.StatusInternalServerError),
		http.StatusInternalServerError)
}

func main() {
	http.HandleFunc("/script.js", scriptHandler)
	http.HandleFunc("/", htmlHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
    

Чтобы попытаться
использовать приложение, перейдите по ссылке: http://localhost:8080 и
попробуйте отправить <img src=1 onerror”alert(1)”/> как и раньше. Эта атака сработала бы и без CSP, но
поскольку CSP не допускает inline-скриптов, вы должны увидеть примерно такой вывод в консоли браузера:

«Отказано в выполнении встроенного обработчика событий, поскольку он нарушает следующую директиву CSP: “script-src ‘nonce-XauzABRw9QtE0bzoiRmslQ==’ ‘unsafe-inline’ ‘unsafe-eval’ ‘strict-dynamic’ https: http:” Обратите внимание, что ‘unsafe-inline‘ игнорируется, если в исходном списке присутствует либо хэш, либо значение nonce.»

Почему сценарий не
запустился? Рассмотрим
CSP подробнее.

Фрагмент 13: Базовый CSP. Nonce повторно генерируется для каждого запроса.
        script-src 'strict-dynamic' 'nonce-XauzABRw9QtE0bzoiRmslQ==';
object-src 'none';
base-uri 'none';
    
Что делает эта политика? Директива script-src включает strict-dynamic и значение nonce, используемое для загрузки скриптов. Это означает, что единственные скрипты, которые будут загружены, находятся в script elements, где nonce включен в атрибут, а значит inline-скрипты не загрузятся. Последние две директивы препятствуют загрузке плагинов и изменению базового URL приложения.

Основная сложность
использования этого подхода заключается в необходимости генерировать nonce и инжектить его в заголовки при каждой загрузке страницы. После этого шаблон
может быть применен ко всем загружаемым страницам.

Соответствующие методы устранения

Content-Type

Вы
должны не только устанавливать свой Content-Type, но и следить, чтобы браузеры не
пытались автоматически определить тип контента. Для
этого используйте заголовок: X-Content-Type-Options:
nosniff
.

Virtual doms

Хотя виртуальные домены
не являются функцией безопасности, использующие их современные фреймворки (
React и Vue) могут помочь смягчить атаки XSS на основе DOM.

Эти фреймворки создают DOM параллельно с тем, который находится в браузере, и сравнивают их. Отличающуюся часть DOM браузера они обновляют. Для этого необходимо создать виртуальный DOM, что приведет к уменьшению использования клиентами innerHTML и подтолкнет разработчиков к переходу на innerText.

React требует
использования атрибута
dangerouslySetInnerHTML, в то время как создатели Vue предупреждают, что использование
innerHTML может привести к появлению уязвимостей.

Заключение

Если вы дочитали до
конца, у вас может появиться желание разобраться, как работают браузеры, что такое ошибки
XSS и насколько важно понимать, как от них избавиться.
XSS трудно искоренить, поскольку приложения становятся все больше и все сложнее. Применяя упомянутые в статье методы, можно сделать жизнь злоумышленников трудной.

Удачи в борьбе и учебе!

Дополнительные материалы:

07
Мар
2021

🕸 Самые удобные браузеры для веб-разработчиков

Правильный выбор инструментов очень важен. В небольшом обзоре мы рассмотрим наиболее продвинутые браузеры для разработки фронтенда.

Если какое программное обеспечение разработчики…

03
Мар
2021

🎨 50 онлайн-инструментов для дизайна: веб-сайты и мобильные приложения

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

27
Фев
2021

🕸 Инструменты веб-разработчика: сервисы и расширения, о которых в 2021 году должен знать каждый

Оперативно проверить сайт или приложение, найти баги и улучшить проект веб-разработчикам помогут специальные сервисы и расширения. Мы собрали более 25 инструментов, упрощающих жизнь программисту.

25
Фев
2021

☕ 25 полезных плагинов и библиотек JavaScript, о которых вы можете не знать

На «ванильном» JavaScript сейчас почти никто не пишет, но кроме мощных фреймворков есть и небольшие библиотеки с интересными возможностями. В наш список попали наиболее полезные из них, часто применяемые веб-разработчиками.

04
Фев
2021

☕ Альтернативные фреймворки JavaScript: есть ли жизнь за пределами большой тройки?

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