Hola, Amigos! Вот и прошла IT-конференция BOOST😍 Мы много общались с другими компаниями, выступали с лекциями, делились факапами, веселились на афтепати, гуляли по Сколково и знакомились с крутыми специалистами. Можем смело заявить, что закрыли все галочки в бинго участника конференции.
Показываем в карточках, как прошли для нас эти 2 дня!
Показываем в карточках, как прошли для нас эти 2 дня!
❤5🔥3😍3
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. При настройке диплинков в наше приложение иногда требуется сделать так, чтобы только определенные ссылки вели в приложение и наоборот. В этой небольшой серии постов мы разберем, как поступать в таких ситуациях.
Начнем со случаев, когда переход должен быть только по определенным путям.
Как и для любых других диплинков, настройка будет внутри проекта для Android и в файле
Для Android нужно открыть файл
Такой код позволит нам открывать только страницы, чей URL начинается с https://example.com/sample.
Используйте
Используйте
Если вы только настраиваете диплинки в ваше приложение, то не забудьте подготовить и загрузить на ваш сайт файл
Давайте сделаем то же самое и для iOS. Откроем или создадим файл
Если нужно сделать переход именно на эту страницу:
Если можно позволить переход на любого потомка этой страницы:
И если в пути содержится часть, но мы не знаем ее точного места:
После этого нужно загрузить этот файл на сервер и подождать, пока AASA-Bot заберет его на CDN компании Apple. Обычно это занимает до суток.
Начнем со случаев, когда переход должен быть только по определенным путям.
Как и для любых других диплинков, настройка будет внутри проекта для Android и в файле
apple-app-site-association для iOS.Для Android нужно открыть файл
AndroidManifest.xml вашего проекта и там добавить код (или изменить его, если вы уже настраивали диплинки до этого):<intent-filter android:autoVerify=”true” tools:targetApi=”m”>
<action android:name=”android.intent.action.VIEW” />
<category android:name=”android.intent.category.DEFAULT />
<category android:name=”android.intent.category.BROWSABLE />
<data
android:scheme=”https”
android:host=”example.com”
android:pathPrefix=”/sample”
/>
</intent-filter>
Такой код позволит нам открывать только страницы, чей URL начинается с https://example.com/sample.
Используйте
path, чтобы указать только 1 ссылку:<data android:path="/sample" />
Используйте
pathSuffix, если нужно указать только окончание URL:<data android:pathSuffix="ample" />
Если вы только настраиваете диплинки в ваше приложение, то не забудьте подготовить и загрузить на ваш сайт файл
assetlinks.json. Как он выглядит и создается рассказано в этой статье, которую мы переводили для вас.Давайте сделаем то же самое и для iOS. Откроем или создадим файл
apple-app-site-association. Тут нас интересует массив components внутри объекта details. Существует несколько вариантов реализации:Если нужно сделать переход именно на эту страницу:
{
“/”: “/sample”,
“comment”: “Откроет только https://example.com/sample”
}
Если можно позволить переход на любого потомка этой страницы:
{
“/”: “/sample/*”,
“comment”: “Откроет также https://example.com/sample/first”
}
И если в пути содержится часть, но мы не знаем ее точного места:
{
“#”: “ample”,
“comment”: “Откроет также https://example.com/mySample”
}
После этого нужно загрузить этот файл на сервер и подождать, пока AASA-Bot заберет его на CDN компании Apple. Обычно это занимает до суток.
👍6❤4🔥4
Книга — настоящий must-have для тех, кто хочет разобраться во Flutter с нуля или прокачать свои навыки. Авторы — сильнейшие практики из индустрии: Станислав Ильин (Поток), Юрий Петров (Friflex), Станислав Чернышев (СПбГУАП) и наш Павел Гершевич.
— Пошаговое изучение Flutter: от Dart и верстки до сборки проекта, готового к публикации;
— Сквозной проект — Тетрис, который развивается от главы к главе;
— Два лабораторных практикума от Surf и MadBrains;
— Отдельный курс на Stepik с тестами для закрепления материала.
На написание ушло почти полтора года, и результат того стоит: получилась настольная книга по кроссплатформенной разработке, которая объединяет теорию, практику и настоящий опыт разработчиков. Идеальный старт для тех, кто только знакомится с Flutter, и полезный источник инсайтов для опытных разработчиков.
А приобрести книгу можно на официальном сайте издательства и на маркетплейсах: Ozon, Wildberries.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥29❤9👏5👍2🥰1
Hola, Amigos! Очень нужна ваша поддержка на Tagline Awards! Сейчас идет народное голосование, в котором у нас участвует 4 проекта:
⚙️ Сайт-путеводитель для самой северной точки Евразии — если Териберка надоела, можно заглянуть на Таймыр к оленям :) Сделали все, чтобы выбрать экскурсию и подобрать маршрут было удобно
⚙️ Travelpayouts: перезапустили инструмент для поиска авиабилетов — освежили дизайн и внутреннюю логику, осуществили поддержку 61 языка, включая арабский, чтобы справа налево тоже читалось
⚙️ Мобильное приложение CMstore — запустили приложение, где можно купить (или просто посмотреть) дайсоны, последние айфоны и другую технику
⚙️ Народный рейтинг «Люди ИТ-индустрии» — наш дебют в мероприятиях. Совместно с Alto и Телеграмошной запустили рейтинг, где можно голосовать не за кейсы или компании, а за людей, которые раскачивают индустрию
Будем рады и благодарны вашим голосам❤️
Будем рады и благодарны вашим голосам
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥2👏1
Hola, Amigos! Заканчиваем год, но продолжаем выступать на мероприятиях!
11 декабря наш Mobile Team Lead Павел Гершевич выступит с докладом «Как не стоит делать корзину для мобильного e-com приложения». В своем выступлении он поделится:
⚙️ почему лучше вести разработку с одной командой, а не с несколькими разными;
⚙️ почему проектировать API должен тот, кто будет его использовать, а не разработчик бэкенда;
⚙️ опыт исправления ошибкок на проекте, где API диктовалось не командой МП, а командой Backend.
А для самых внимательных слушателей Павел подготовил подарок! За лучший вопрос он подарит экземпляр своей книги «Основы Flutter», о презентации которой мы недавно писали.
Митап пройдет в Красноярске, регистрируйтесь на сайте!
11 декабря наш Mobile Team Lead Павел Гершевич выступит с докладом «Как не стоит делать корзину для мобильного e-com приложения». В своем выступлении он поделится:
А для самых внимательных слушателей Павел подготовил подарок! За лучший вопрос он подарит экземпляр своей книги «Основы Flutter», о презентации которой мы недавно писали.
Митап пройдет в Красноярске, регистрируйтесь на сайте!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🔥3
Hola, Amigos! Хотим поделиться с вами классной новостью. 5 декабря прошла церемония награждения премии Tagline Awards 2025 — главной награды за достижения в digital-сфере.
В премии участвует 500+ известных брендов и агентств, а награды вручаются за уровень работ, качество их исполнения и эффективность решения коммерческих задач🔥
Делимся победами! В этом году мы заняли:
🏆 2 место в номинации «Лучший сайт об услугах» с кейсом разработки сайта для федеральной сети клиник
🏆 3 место в номинации «Лучшее ритейл-приложение» с кейсом мобильного приложения CMstore
🏆 А также мы попали в шорт-лист номинации «Лучшая кампания для искусства/культуры/развлечений» с нашим первый мероприятием — народным рейтингом «Люди ИТ-индустрии»
Спасибо команде за работу и заказчикам за доверие❤️ Особенно радует, что наш рейтинг, который мы вместе с Alto и Телеграмошной реализовали за пару месяцев, попал в шорт-лист! Замотивированы развиваться и дальше предлагать рынку свежие идеи ⚙️
Пишите свое мнение в комментариях, мы будем рады вашему фидбеку)
В премии участвует 500+ известных брендов и агентств, а награды вручаются за уровень работ, качество их исполнения и эффективность решения коммерческих задач🔥
Делимся победами! В этом году мы заняли:
🏆 2 место в номинации «Лучший сайт об услугах» с кейсом разработки сайта для федеральной сети клиник
🏆 3 место в номинации «Лучшее ритейл-приложение» с кейсом мобильного приложения CMstore
🏆 А также мы попали в шорт-лист номинации «Лучшая кампания для искусства/культуры/развлечений» с нашим первый мероприятием — народным рейтингом «Люди ИТ-индустрии»
Спасибо команде за работу и заказчикам за доверие
Пишите свое мнение в комментариях, мы будем рады вашему фидбеку)
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍5🔥5
Hola, Amigos! Сегодня начнем серию постов о банковских приложениях на Flutter. В таких проеках цена ошибок в безопасности намного выше, чем в обычных mobile-проектах. В нескольких частях разберем практические подходы к защите Flutter-приложений в банковском контексте.
В первой части начнем с фундамента: хранения данных и аутентификации. Именно здесь чаще всего закладываются уязвимости, которые потом сложно исправить.
1. Не храните данные в открытом виде
Сохранение токенов в
Используйте зашифрованное хранилище:
2. Только token-based аутентификация
Cookies и сессии не подходят для банковских приложений. Токен должен добавляться ко всем запросам централизованно:
3. Никогда не хардкодьте личные данные
API-ключи и токены не должны попадать в репозиторий:
Правильно:
Передача через CI:
А что происходит, когда аутентификация уже выстроена, но трафик можно перехватить, а OTP проверяется на клиенте?
В следующей части разберем сетевую безопасность, SSL pinning и работу с OTP⚙️
В первой части начнем с фундамента: хранения данных и аутентификации. Именно здесь чаще всего закладываются уязвимости, которые потом сложно исправить.
1. Не храните данные в открытом виде
Сохранение токенов в
SharedPreferences — прямой путь к компрометации:
final prefs = await SharedPreferences.getInstance();
prefs.setString("token", token);
Используйте зашифрованное хранилище:
final secureStorage = FlutterSecureStorage();
await secureStorage.write(
key: "access_token",
value: token,
);
final token = await secureStorage.read(key: "access_token");
2. Только token-based аутентификация
Cookies и сессии не подходят для банковских приложений. Токен должен добавляться ко всем запросам централизованно:
class AuthInterceptor extends Interceptor {
final FlutterSecureStorage storage;
AuthInterceptor(this.storage);
@override
void onRequest(RequestOptions options, handler) async {
final token = await storage.read(key: "access_token");
if (token != null) {
options.headers["Authorization"] = "Bearer $token";
}
handler.next(options);
}
}
3. Никогда не хардкодьте личные данные
API-ключи и токены не должны попадать в репозиторий:
const apiKey = "sk_test_123456";
Правильно:
const apiKey = String.fromEnvironment("API_KEY");
Передача через CI:
--dart-define=API_KEY=your_key_here
А что происходит, когда аутентификация уже выстроена, но трафик можно перехватить, а OTP проверяется на клиенте?
В следующей части разберем сетевую безопасность, SSL pinning и работу с OTP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥5❤2👎1👀1
Hola, Amigos! Продолжаем разговор о безопасности приложений на Flutter.
Даже при корректной аутентификации приложение остается уязвимым, если сетевой слой и серверная валидация реализованы неправильно. В этой части поговорим о защите сетевых запросов, доверии к данным и проверке OTP.
1. SSL pinning — обязательное требование
Без pinning HTTPS не спасает от атаки MITM (Man In The Middle), когда злоумышленники перехватывают трафик между приложением и сервером, а потом читают или подменяют запросы через прокси или wi-fi:
Это блокирует:
- proxy
- fake Wi-Fi
- подмену сертификатов
2. OTP всегда проверяется на сервере
Проверка OTP на клиенте — критическая уязвимость:
Только сервер:
3. Клиентская валидация — не финальная. Данные всегда проверяются на сервере:
Эти меры закрывают большую часть рисков, но сами по себе они не решают все. Даже при защищенном трафике и корректной логике на бэке приложение остается уязвимым на уровне устройства и интерфейса.
В следующей части разберем защиту UI, работу с сессиями и ограничения на уровне устройства.
Даже при корректной аутентификации приложение остается уязвимым, если сетевой слой и серверная валидация реализованы неправильно. В этой части поговорим о защите сетевых запросов, доверии к данным и проверке OTP.
1. SSL pinning — обязательное требование
Без pinning HTTPS не спасает от атаки MITM (Man In The Middle), когда злоумышленники перехватывают трафик между приложением и сервером, а потом читают или подменяют запросы через прокси или wi-fi:
final context = SecurityContext(withTrustedRoots: false);
context.setTrustedCertificatesBytes(certBytes);
final httpClient = HttpClient(context: context);
final dio = Dio()
..httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () => httpClient,
);
Это блокирует:
- proxy
- fake Wi-Fi
- подмену сертификатов
2. OTP всегда проверяется на сервере
Проверка OTP на клиенте — критическая уязвимость:
if (enteredOtp == "123456") success();
Только сервер:
await api.verifyOtp(
mobile: mobile,
otp: enteredOtp,
);
3. Клиентская валидация — не финальная. Данные всегда проверяются на сервере:
bool isValidAmount(String value) {
final amount = double.tryParse(value);
return amount != null && amount > 0 && amount < 100000;
}
Эти меры закрывают большую часть рисков, но сами по себе они не решают все. Даже при защищенном трафике и корректной логике на бэке приложение остается уязвимым на уровне устройства и интерфейса.
В следующей части разберем защиту UI, работу с сессиями и ограничения на уровне устройства.
🔥12❤3😍3
Hola, Amigos! Даже идеально защищенный backend не поможет, если приложение уязвимо на уровне устройства. В финальной части посмотрим на безопасность со стороны устройства и пользовательского интерфейса.
1. Запрещайте скриншоты на чувствительных экранах
Некоторые чувствительные данные не должны попадать в скриншоты:
2. Используйте биометрию
Биометрия нужна не только для логина.
Подходит для различных сценариев:
- входа
- платежей
- доступа к профилю
3. Автоматический логаут и контроль сессии
Выход при:
- уходе в фон
- бездействии
- истечении токена
4. Root / Jailbreak — блокировать
Не забывайте про использование в нескольких местах и рандомных триггерах, чтобы труднее было подвергнуть приложение реверс-инжинирингу.
5. Код и логи в продакшене
Надеюсь, советы были полезны и помогут избежать типовых ошибок при разработке приложений на Flutter. Если тема откликнулась — пишите в комментарии!
1. Запрещайте скриншоты на чувствительных экранах
Некоторые чувствительные данные не должны попадать в скриншоты:
@override
void initState() {
super.initState();
if (Platform.isAndroid) {
FlutterWindowManager.addFlags(
FlutterWindowManager.FLAG_SECURE,
);
}
}
2. Используйте биометрию
Биометрия нужна не только для логина.
final auth = LocalAuthentication();
await auth.authenticate(
localizedReason: "Verify to access your bank account",
options: const AuthenticationOptions(
biometricOnly: true,
),
);
Подходит для различных сценариев:
- входа
- платежей
- доступа к профилю
3. Автоматический логаут и контроль сессии
class SessionManager {
Timer? _timer;
void start(void Function() onExpire) {
_timer?.cancel();
_timer = Timer(
const Duration(minutes: 5),
onExpire,
);
}
void refresh() {
_timer?.cancel();
}
}
Выход при:
- уходе в фон
- бездействии
- истечении токена
4. Root / Jailbreak — блокировать
final isRooted = await RootChecker.isRooted();
if (isRooted) {
exit(0);
}
Не забывайте про использование в нескольких местах и рандомных триггерах, чтобы труднее было подвергнуть приложение реверс-инжинирингу.
5. Код и логи в продакшене
flutter build apk --obfuscate --split-debug-info=./symbols
flutter build ios --obfuscate
if (kDebugMode) {
print("Token: $token");
}
Надеюсь, советы были полезны и помогут избежать типовых ошибок при разработке приложений на Flutter. Если тема откликнулась — пишите в комментарии!
❤8🔥7❤🔥2👍2