Flutter. Много – Telegram
Flutter. Много
2.73K subscribers
353 photos
23 videos
266 links
Заказать мобильную разработку: https://amiga.agency/?utm_source=tg
Заказать рекламу в канале @amiga_agency_bot

Новости Flutter-разработки, дайджесты мероприятий, личный опыт.
Download Telegram
Hola, Amigos! Вот и прошла IT-конференция BOOST😍 Мы много общались с другими компаниями, выступали с лекциями, делились факапами, веселились на афтепати, гуляли по Сколково и знакомились с крутыми специалистами. Можем смело заявить, что закрыли все галочки в бинго участника конференции.

Показываем в карточках, как прошли для нас эти 2 дня!
5🔥3😍3
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. При настройке диплинков в наше приложение иногда требуется сделать так, чтобы только определенные ссылки вели в приложение и наоборот. В этой небольшой серии постов мы разберем, как поступать в таких ситуациях.

Начнем со случаев, когда переход должен быть только по определенным путям.

Как и для любых других диплинков, настройка будет внутри проекта для 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. Обычно это занимает до суток.
👍64🔥4
🙂 Hola, Amigos! На связи команда Amiga. У нас оооочень крутая новость — наш Mobile Team Lead, Павел Гершевич, стал соавтором книги «Основы Flutter».

Книга — настоящий must-have для тех, кто хочет разобраться во Flutter с нуля или прокачать свои навыки. Авторы — сильнейшие практики из индустрии: Станислав Ильин (Поток), Юрий Петров (Friflex), Станислав Чернышев (СПбГУАП) и наш Павел Гершевич.

⚙️ Что внутри:
— Пошаговое изучение Flutter: от Dart и верстки до сборки проекта, готового к публикации;
— Сквозной проект — Тетрис, который развивается от главы к главе;
— Два лабораторных практикума от Surf и MadBrains;
— Отдельный курс на Stepik с тестами для закрепления материала.

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

А приобрести книгу можно на официальном сайте издательства и на маркетплейсах: Ozon, Wildberries.

❤️ — поддержим Павла с долгожданным выходом!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥299👏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», о презентации которой мы недавно писали.

Митап пройдет в Красноярске, регистрируйтесь на сайте!
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 и Телеграмошной реализовали за пару месяцев, попал в шорт-лист! Замотивированы развиваться и дальше предлагать рынку свежие идеи ⚙️

Пишите свое мнение в комментариях, мы будем рады вашему фидбеку)
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍5🔥5
Hola, Amigos! Сегодня начнем серию постов о банковских приложениях на Flutter. В таких проеках цена ошибок в безопасности намного выше, чем в обычных mobile-проектах. В нескольких частях разберем практические подходы к защите Flutter-приложений в банковском контексте.

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

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🔥52👎1👀1
Hola, Amigos! Продолжаем разговор о безопасности приложений на Flutter.

Даже при корректной аутентификации приложение остается уязвимым, если сетевой слой и серверная валидация реализованы неправильно. В этой части поговорим о защите сетевых запросов, доверии к данным и проверке 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, работу с сессиями и ограничения на уровне устройства.
🔥123😍3
Hola, Amigos! Даже идеально защищенный backend не поможет, если приложение уязвимо на уровне устройства. В финальной части посмотрим на безопасность со стороны устройства и пользовательского интерфейса.

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