Файл: Руководство пользователя для разработанной системы. Пятый раздел приводит данные по информационной безопасности приложения.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 23.11.2023

Просмотров: 156

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

2.5 Выводы по разделу

В результате обзора технических средств и анализа поставленной задачи для реализации дипломного проекта была выбрана кросс-платформа ASP.NET Core, так как данная платформа предоставляет весь нужный функциональный набор для создания веб-ресурса. Исходя из выбранной платформы, языком, для написания веб-ресурса был выбран C#, так как данный язык программирования позволяет создавать различные безопасные и надежные приложения, работающие на платформе .NET Core. В качестве СУБД был выбран объектно-реляционный PostgreSQL. В основу работы с базой данных была выбрана технология конструктора EF. Основой серверной части проекта был выбран шаблон проектирования Web API, архитектуры REST для работы с авторизацией и GraphQL для обработки данных. Для реализации клиентской части был выбран фреймфорк Flutter.

Итоговыми ключевыми компонентами решения являются:

  • клиентское приложение;

  • база данных серверного приложения;

– серверное приложение.

Выполнено проектирование разработки. Представлены UML диаграммы/



3 Разработка программного обеспечения

3.1 Разработка программного средства


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

На последнем этапе необходимо разработать и реализовать сервер и клиентское приложение.

В ходе разработки были реализованы все требования технического задания.

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

3.2 Разработка компонентов клиентского приложения


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

Для разработки приложения был выбран архитектурный стиль строения приложения BLoCBusiness Logic Components. Данный архитектурный стиль позволят нам контролировать состояние компонентов с помощью событий бизнес-логики. В листинге 3.1 представлен пример BLoC компонента.

Отделение UI от бизнес-логики для Flutter жизненно необходимо. Согласитесь, что карабкаться вверх-вниз по дереву виджетов (UI-компонентов) в поисках нужной вам логики — не самая приятная вещь. Особенно, если верстка и так содержит очень много кода и разбросана по разным файлам. Кроме того, если мы следуем заветам Clean Architecture (а мы им следуем, не так ли?), то в нашем UI вообще не должно быть ничего лишнего. Равно как и бизнес-логика ничего не должна знать про UI, который к ней обращается. Благодаря такому тщательному разделению ответственностей мы получаем полностью изолированный компонент, который можно легко тестировать независимо от UI и использовать в другом окружении. Этот компонент и есть наш Bloc.

Каждый Bloc поддерживает общий интерфейс BlocBase, содержащий в себе только один обязательный к реализации метод dispose. Он нужен, чтобы не забыть реализовать освобождение ресурсов, занятых Bloc-ом, например, закрыть активные потоки. Для того чтобы вы могли получить доступ к Bloc-у из любого узла дерева виджетов, корнем этого дерева становится такая сущность, как BlocProvider. Идея заключается в том, что наш провайдер, точно такой же виджет, который состоит из двух слагаемых: Bloc, к которому будут обращаться виджеты, и дерево виджетов, которое мы видим на экране.



class AuthCubit extends Cubit {

AuthCubit({required AuthRepositoryBase repository})

: _repository = repository,

super(const AuthState());
final AuthRepositoryBase _repository;
Future loadTokenState() async {

try {

emit(state.copyWith(status: AuthStatus.loading));
await _repository.checkToken();

final String? token = await _repository.getToken();
emit(state.copyWith(status: AuthStatus.loaded, token: token));

} on DioError catch (e) {

emit(state.copyWith(status: AuthStatus.error, error: e));

}

}
Future signIn(String login, String email, String password,

String confirmPassword) async {

try {

emit(state.copyWith(status: AuthStatus.loading));
final String? token =

await _repository.signIn(login, email, password, confirmPassword);
emit(state.copyWith(status: AuthStatus.loaded, token: token));

} on DioError catch (e) {

emit(state.copyWith(status: AuthStatus.error, error: e));

}

}
Future register(String login, String email, String password,

String confirmPassword) async {

try {

emit(state.copyWith(status: AuthStatus.loading));
final String? token =

await _repository.createUser(login, email, password, confirmPassword);
emit(state.copyWith(status: AuthStatus.loaded, token: token));

} on DioError catch (e) {

emit(state.copyWith(status: AuthStatus.error, error: e));

}

}
Future signOut() async {

try {

emit(state.copyWith(status: AuthStatus.loading));
await _repository.signOut();
emit(state.copyWith(status: AuthStatus.loaded, token: null));

} on DioError catch (e) {

emit(state.copyWith(status: AuthStatus.error, error: e));

}

}

}

Листинг 3.1 – BloC компонент авторизации

3.2.1 Разработка аутентификации


Аутентификация в приложении имеет собственный подраздел в хранилище, которое предоставляется зависимостью firebase_core и хранит информацию, необходимую для входа в приложение с использованием выбранного в настройках Firebase Auth способа с помощью пароля и электронного адреса. Также там хранятся данные, необходимые для запоминания текущего пользователя, чтобы в последующем он мог осуществлять вход в приложение, минуя экран аутентификации. Функция обработки аутентификации в качестве сотрудника указана в листинге 3.2.

Provider.of(context, listen: false)

.signInWithEmailAndPassword(

email: loginController.text,

password: passwordController.text,

).then((auth) {

print("${auth.user.uid} ${auth.user.email}");

Provider.of(context, listen: false)

.collection("users")

.getDocuments()

.then((value) {

var doc = value.documents.firstWhere((element) =>

element.documentID == auth.user.uid, orElse: () {

Provider.of(context, listen: false)

.signOut();

return;

});

if (doc != null) {

if (codeController.text == doc.data['code']) {

SharedPreferences.getInstance().then((prefs) {

prefs.setBool(

'staff', true);

Router.navigator.pushReplacementNamed(Router.ordersPage);

});

}

}

})

})


Листинг 3.2 – Функция аутентификации пользователя как сотрудника

Provider – аналог dependency injection для Flutter, зависимость помогает передать компоненты используемые для взаимодействия с внешними сервисами вниз по дереву виджетов. Это позволяет избежать повторения созданий объектов для взаимодействия с внешними сервисами. В листинге 3.3 представлен код для подключения компонентов к зависимости Provider.

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MultiProvider(

providers: [

Provider(create: (_) => FirebaseAuth.instance),

Provider(create: (_) => Firestore.instance),

Provider(create: (_) => FirebaseStorage.instance),

Provider(create: (_) => Geolocator()),

Provider(create: (_) => FirebaseMessaging()),

BlocProvider(create: (_) => AuthBloc())

],

child: MaterialApp(

debugShowCheckedModeBanner: false,

title: 'Material App',

theme: ThemeData.light().copyWith(

primaryColor: Colors.deepOrange[700],

accentColor: Colors.deepOrangeAccent,

),

builder: ExtendedNavigator(router: Router())

),

);

}

}

Листинг 3.3 – Главный класс приложения с подключенными компонентами

Сама же функция аутентификации пользователя как сотрудника выбирается по коду выше в зависимости от состояния BLoC компонента AuthBloc. В листинге 3.4 представлен код, который меняет дерево виджетов в зависимости от состояния компонента AuthBloc [6].

BlocBuilder(

builder: (context, state) {

loginController.clear();

passwordController.clear();

if (state is AuthRegisterState)

return AnimatedSwitcher(

duration: Duration(milliseconds: 590),

child: Form(

key: _formKey,

child: buildRegister(context),

),

);

else if (state is AuthStaffLoginState)

return AnimatedSwitcher(

duration: Duration(milliseconds: 590),

Листинг 3.4 – Функция смены функциональности по состоянию BLoC

child: Form(

key: _formKey,

child: buildStaffLogin(context),

),

);

return AnimatedSwitcher(

duration: Duration(milliseconds: 590),

child: Form(

key: _formKey,

child: buildLogin(context),

),

);},)


Продолжение листинга 3.4

3.3 Настройка рабочей среды

Первым делом необходимо установить необходимые плагины и настроить редактор Android Studio. Для разработки кроссплатформенных приложений на Flutter необходимо установить сам фреймворк Flutter. Для разработки мобильных приложений на Android нужно установить Android SDK. На рисунке 2.4 можно увидеть настройку Android SDK. Для разработки десктопных приложений для Windows нужно установить Visual Studio Build Tools с поддержкой C++.



Рисунок 2.4 – Экран настройки и установки Android SDK
Android SDK включает в себя необходимые инструменты, чтобы помочь Android-разработчикам в совершении первых шагов: различные API (прикладной программный интерфейс), разработанные Google для управления функциями устройства и интеграции сервисов, полнофункциональный эмулятор для тестирования приложений, а также все необходимые текстовые материалы, чтобы дать начало для программирования под Android.
3.4 Архитектурный стиль строения и зависимости приложения

BLoC (BusinessLogicComponent) ­ это архитектурный шаблон, представленный Google. Идея заключается в том, чтобы иметь отдельные компоненты (компоненты BLoC), содержащие только бизнес-логику, которая должна легко использоваться различными приложениями Dart. Для AndroidStudio, Google предоставляют одноименный плагин для автогенерации bloc компонентов [3].

Трёхслойный архитектурный стиль – это архитектурный шаблон, представляющий из себя три слоя разделения логики приложения:

  • уровень представления.

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