Как добавить аутентификацию в приложение React Native?
Аутентификация является основным компонентом почти каждого приложения.
В этой практической статье вы найдете пошаговое руководство по началу работы с аутентификацией в React Native.
Кроме того, здесь будут описаны основы аутентификации, ее сравнение с авторизацией, процесс аутентификации и преимущества ее использования.
Contents
- 1 Что такое аутентификация?
- 2 Поток аутентификации
- 3 Аутентификация и авторизация
- 4 Преимущества аутентификации
- 5 Как добавить аутентификацию в приложение React Native?
- 6 Заключение
Что такое аутентификация?
Аутентификация – это процесс проверки чьей-либо личности. Вообще говоря, существует три способа проверки подлинности: с помощью:
- То, что вы знаете (например, пароль, PIN-код).
- Что-нибудь, что у вас есть (например, мобильный телефон, ключи)
- То, чем вы являетесь (например, отпечаток пальца, радужная оболочка глаза)
Большинство приложений используют первый вариант, но многие сочетают несколько из них, чтобы повысить уровень безопасности. Эта концепция называется многофакторной аутентификацией (MFA).
Поток аутентификации
Общий поток аутентификации работает следующим образом:
- Пользователь отправляет свой пароль на сервер.
- Сервер хэширует пароль и сравнивает его с хэшем пароля в базе данных.
- Если хэши совпадают, сервер создает сессию и отправляет токен сессии пользователю. С другой стороны, если хэши не совпадают, возникает ошибка.
- Затем пользователь использует токен сессии при каждом запросе. При каждом запросе сервер проверяет наличие и действительность маркера.
Приведенная выше схема представляет собой так называемую аутентификацию с помощью токенов. Другие системы аутентификации включают JSON Web Token (JWT), базовую аутентификацию доступа, социальный вход и так далее.
Аутентификация и авторизация
Аутентификация – это проверка личности пользователя, а авторизация – проверка наличия у пользователя достаточных полномочий для выполнения того или иного действия.
Модели авторизации включают обязательный контроль доступа (MAC), дискреционный контроль доступа (DAC), авторизацию на основе ролей и другие.
Преимущества аутентификации
Давайте рассмотрим некоторые преимущества использования аутентификации в ваших мобильных приложениях.
Безопасность
Аутентификация может защитить ваше приложение от несанкционированного доступа и гарантировать, что только легитимные пользователи имеют доступ к вашему сервису.
Это поможет предотвратить утечку данных и кибератаки, а также обеспечит безопасность и надежность вашей среды приложений.
Персонализация
Аутентификация позволяет персонализировать работу пользователя в приложении. Когда пользователи входят в систему, они получают доступ к индивидуальным настройкам, предпочтениям и рекомендациям, соответствующим их потребностям.
Такая персонализация делает приложение более привлекательным и удобным для пользователя. Она помогает удерживать пользователей, обеспечивая более релевантный и приятный опыт.
Требования законодательства
Законы некоторых стран требуют проверять личность пользователей. Примером этого является Know Your Customer (KYC).
Почти все финансовые приложения обязаны это делать. Чтобы соответствовать этим правилам и защитить личные данные пользователей, необходимо иметь соответствующую систему аутентификации.
Как добавить аутентификацию в приложение React Native?
В этой части статьи будет представлено пошаговое руководство по добавлению аутентификации Back4app в приложение React Native(Expo).
Пререквизиты
- Базовое понимание бэкенда как услуги (BaaS)
- JavaScript IDE, Node.js и эмулятор мобильного устройства или физическое устройство
- Умение читать и писать код на JavaScript
- Опыт работы с React Native и Expo
- Бесплатная учетная запись Back4app
Что такое Back4app?
Back4app – одно из лучших решений с открытым исходным кодом для создания Backend as a Service (BaaS). Это зрелая и надежная платформа, существующая с 2015 года.
Среди его основных возможностей – базы данных в реальном времени, функции Cloud Code, автоматическая генерация RESTful/GraphQL API и многое другое!
Back4app имеет простую в использовании и интуитивно понятную панель администратора, а также интерфейс командной строки (CLI) для более опытных пользователей.
Он также предоставляет SDK для самых популярных языков программирования и фреймворков, таких как JavaScript, PHP, Flutter и Dart.
Самое приятное, что Back4app предлагает бесплатный уровень. Бесплатный уровень отлично подходит для тестирования и создания прототипов, и он включает в себя следующее:
- 25 тыс. заявок в месяц
- Память для хранения данных объемом 250 МБ
- Передача данных 1 ГБ
- Файловое хранилище объемом 1 ГБ
Почему стоит использовать Back4app?
- Поддержка социальной аутентификации
- Предоставляет SDK для большинства языков программирования и фреймворков
- Простая настройка и использование
- Отличная поддержка клиентов
Чтобы узнать, как аутентификация Back4app сравнивается с аутентификацией Firebase, прочитайте статью The Ultimate Guide to React Firebase Authentication.
Введение в проект – начало работы с аутентификацией React Native
Мы создадим готовое к производству приложение React Native, использующее аутентификацию Back4app. Приложение позволит пользователям регистрироваться, входить в систему и управлять своими профилями.
Кроме того, в приложении будет две вкладки: одна для аутентифицированных пользователей, другая – для неаутентифицированных.
Конечный продукт будет выглядеть примерно так:
Давайте начнем кодировать!
Бэкэнд (Back4app)
В этом разделе мы создадим приложение Back4app, расширим стандартную модель пользователя и получим API-ключи, необходимые для подключения к бэкенду.
Создать приложение
Во-первых, войдите в свой аккаунт Back4app или создайте его, если у вас его еще нет.
Когда вы войдете в систему, вы будете перенаправлены в список приложений. Нажмите “Создать новое приложение”, чтобы создать новое приложение.
Платформа Back4app позволяет развернуть два типа приложений – либо Backend as a Service (BaaS), либо Containers as a Service (CaaS). Аутентификация включена в BaaS, поэтому выберите ее.
Далее дайте своему приложению описательное имя, оставьте базу данных как NoSQL и нажмите “Создать”.
Подождите около двух минут, пока платформа создаст приложение. Back4app сделает все: от создания слоя приложения до настройки базы данных, безопасности, масштабирования и прочего.
После этого вы будете перенаправлены в интерфейс базы данных.
Изменить базу данных
Далее поговорим о классах баз данных.
Каждый класс базы данных Back4app поставляется со следующими полями по умолчанию:
+-----------+------------+-----------------------------------------+
| Data type | Name | Description |
+-----------+------------+-----------------------------------------+
| String | objectId | Object's unique identifier |
+-----------+------------+-----------------------------------------+
| Date | createdAt | Date of object creation |
+-----------+------------+-----------------------------------------+
| Date | updatedAt | Date of object's last update |
+-----------+------------+-----------------------------------------+
| ACL | ACL | Access Control List (security features) |
+-----------+------------+-----------------------------------------+
А класс User
содержит несколько дополнительных полей:
+-----------+----------------+--------------------------+----------+
| Data type | Name | Default value | Required |
+-----------+----------------+--------------------------+----------+
| String | username | | yes |
+-----------+----------------+--------------------------+----------+
| String | email | | no |
+-----------+----------------+--------------------------+----------+
| Boolean | emailVerified | false | no |
+-----------+----------------+--------------------------+----------+
| String | password | | yes |
+-----------+----------------+--------------------------+----------+
| Object* | authData | {} | yes |
+-----------+----------------+--------------------------+----------+
Стандартный пользовательский класс Back4app должен быть хорош для большинства случаев использования. Тем не менее, расширить его очень просто. Чтобы продемонстрировать, как это делается, давайте добавим поле биографии(bio
).
Сначала нажмите кнопку “+ Column” над таблицей базы данных.
В форме создания столбца выберите тип данных “String”, задайте имя bio
, сделайте его обязательным и нажмите кнопку “Добавить”.
Отлично, теперь вы знаете, как работают классы базы данных Back4app и как расширить пользовательскую модель.
Ключи API
Чтобы подключиться к бэкенду с фронтенда, вам потребуется получить API-ключи вашего приложения.
Чтобы получить их, перейдите в приложение Back4app и выберите “Безопасность и ключи” на боковой панели. Обратите внимание на “Ключ клиента” и “Ключ JavaScript”.
Отлично, вот и все со стороны бэкенда.
Фронтенд (React Native)
В этом разделе мы создадим приложение Expo, установим библиотеку компонентов, настроим навигацию, позаботимся об экранах и, наконец, соединим фронтенд с бэкендом.
Создать приложение
Чтобы создать приложение React Native, мы воспользуемся утилитой create-expo-app
. Эта утилита упрощает создание приложений React Native, генерируя структуру каталогов, настраивая TypeScript и т. д.
Сначала выполните следующие команды:
npx create-expo-app@latest back4app-expo-auth
cd back4app-expo-auth
Эта команда также установит
create-expo-app
, если у вас его еще нет.
Вы заметите, что проект bootstraped имеет следующую структуру каталогов:
back4app-expo-auth/
├── app - Layouts, screens
├── assets - Static assets (e.g. images, videos, fonts)
├── components - Reusable components used through the app
├── constants - Static variables & configurations
├── hooks - Custom React hooks
├── scripts - Development scripts
├── app.json - Expo configuration & metadata
├── expo-env.d.ts - Expo TypeScript declarations
├── ...
Запустите сервер разработки:
$ npx expo start
И наконец, нажмите A
, чтобы открыть приложение в эмуляторе Android. В качестве альтернативы можно использовать эмулятор iOS или физическое устройство iOS. После открытия приложения вы увидите стандартный экран Expo.
React Native Paper
Чтобы упростить процесс разработки пользовательского интерфейса, мы будем использовать React Native Paper.
React Native Paper – это простая в использовании, высококачественная библиотека компонентов для приложений React Native. Она предоставляет множество готовых компонентов, охватывающих практически все варианты использования.
Начните с установки его через NPM:
$ npm install react-native-paper react-native-safe-area-context
Если вы делаете сборку для iOS, вам также придется связать нативные части библиотеки:
npx pod-install
Далее настройте Babel так, чтобы не включать неиспользуемые компоненты в производство:
// babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
env: {
production: {
plugins: ["react-native-paper/babel"],
},
},
};
};
Затем перейдите в app/_layout.tsx и оберните приложение в PaperProvider
следующим образом:
// app/_layout.tsx
// ...
export default function RootLayout() {
// ...
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<PaperProvider>
<Stack>
<Stack.Screen name="index" options={{headerShown: false}}/>
<Stack.Screen name="(auth)" options={{headerShown: false}}/>
<Stack.Screen name="(tabs)" options={{headerShown: false}}/>
<Stack.Screen name="+not-found"/>
</Stack>
</PaperProvider>
</ThemeProvider>
);
}
Не забудьте про импорт в верхней части файла:
import {PaperProvider} from "react-native-paper";
Отлично, мы успешно установили библиотеку компонентов.
Контейнер
Еще одна вещь, которую мы сделаем, – это создадим компонент Container
. Этот компонент будет использоваться во всех наших экранах, и он добавит поля со всех сторон, чтобы содержимое не выходило за край экрана.
Создайте файл Container.tsx в папке components:
// components/Container.tsx
import React from "react";
import {View} from "react-native";
export type ContainerProps = {
children: React.ReactNode;
}
export function Container({children}: ContainerProps) {
return (
<View style={{margin: 12}}>
{children}
</View>
);
}
Навигация и экраны
Как уже говорилось во введении к проекту, в нашем приложении будет две навигационные вкладки.
Одна из них предназначена для аутентифицированных пользователей, а другая – для неаутентифицированных. Вкладка для аутентифицированных пользователей позволит им управлять своими профилями, а другая – войти в систему или создать учетную запись.
Для этого сначала создайте следующую структуру каталогов:
app/
├── (auth)/
│ ├── _layout.tsx
│ ├── login.tsx
│ └── register.tsx
├── (tabs)/
│ ├── _layout.tsx
│ └── profile.tsx
├── +html.tsx
├── +not-found.tsx
├── _layout.tsx
└── index.tsx
Более подробную информацию о Expo Router можно найти в официальной документации.
Экспозиционные макеты обычно содержат много шаблонного кода. Я не хочу переполнять статью кодом, поэтому, пожалуйста, возьмите содержимое файлов с GitHub:
Двигаясь дальше, поместите в index.tsx следующее:
// app/index.tsx
import React, {useEffect} from "react";
import {ActivityIndicator} from "react-native-paper";
import {useRouter} from "expo-router";
import {View} from "react-native";
export default function IndexScreen() {
const router = useRouter();
const isAuthenticated = true;
useEffect(() => {
setTimeout(() => {
if (isAuthenticated) {
router.push("profile");
} else {
router.push("login");
}
}, 1000);
}, []);
return (
<View style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}>
<ActivityIndicator
size="large"
animating={true}
/>
</View>
);
}
Файл index.tsx – это точка входа в приложение. В нем мы проверяем, прошел ли пользователь аутентификацию, и соответствующим образом перенаправляем его. Пока что перенаправление происходит на основе переменной isAuthenticated
.
Затем возьмите код для экранов:
Код экранов довольно прост. Это код React Native, который использует React Native Paper для создания форм и других элементов пользовательского интерфейса. Он также использует основные хуки React, такие как useState()
и useEffect()
.
Parse SDK
Для подключения к бэкенду мы будем использовать Parse SDK. SDK предлагает методы для хранения данных, манипулирования ими, аутентификации пользователей и другие возможности.
Сначала установите его с помощью NPM:
$ npm install parse @react-native-async-storage/async-storage --save
$ npm install --save-dev @types/parse
Мы также установили пакет @react-native-async-storage/async-storage
, чтобы сохранять пользовательскую сессию при закрытии приложения. Без него пользователям пришлось бы проходить аутентификацию каждый раз, когда они открывают приложение.
Затем создайте файл .env в корне проекта, как показано ниже:
EXPO_PUBLIC_APPLICATION_ID=<your-back4app-application-id>
EXPO_PUBLIC_JAVASCRIPT_KEY=<your-back4app-client-key>
Обеспечьте замену
<your-back4app-application-id>
и<your-back4app-client-key>
на API-ключи, полученные в разделе статьи, посвященном бэкенду.
Инициализируйте Parse в файле _layout.tsx следующим образом:
// app/_layout.tsx
// ...
import Parse from "parse/react-native.js";
import AsyncStorage from "@react-native-async-storage/async-storage";
import ParseContext from "@/context/parseContext";
Parse.setAsyncStorage(AsyncStorage);
Parse.initialize(
process.env.EXPO_PUBLIC_APPLICATION_ID ?? "",
process.env.EXPO_PUBLIC_JAVASCRIPT_KEY ?? "",
)
Parse.serverURL = "https://parseapi.back4app.com/";
async function testParse() {
try {
const testMessage = new Parse.Object("TestMessage");
testMessage.set("message", "Hello, World!");
await testMessage.save();
} catch (error) {
console.log("Error saving the test message: ", error);
}
}
testParse().then(() => console.log("Successfully connected to Parse!"));
// ...
Мы также включили функцию testParse()
, которая проверяет соединение с Back4app, добавляя в базу данных сообщение “Hello, world!”. Убедитесь, что соединение работает, перезапустив сервер Expo и запустив приложение в эмуляторе.
Перейдите к представлению базы данных вашего приложения и проверьте, видно ли сообщение.
Если вы получите ошибку “Error: crypto.getRandomValues() not supported”. Установите следующие зависимости:
npm install react-native-get-random-values --save
npm i --save-dev @types/react-native-get-random-values
Затем добавьте импорт в верхнюю часть файла _layout.tsx (перед импортом Parse):
import "react-native-get-random-values";
Перезапустите сервер разработки; все должно работать нормально.
Чтобы экземпляр Parse был доступен на всех экранах, мы передадим его с помощью React Context.
Сначала создайте каталог context и поместите в него следующий файл parseContext.ts:
import {createContext} from "react";
const ParseContext = createContext<typeof Parse | null>(null);
export default ParseContext;
Затем оберните им все приложение, передав экземпляр Parse:
// app/_layout.tsx
// ...
return (
<ParseContext.Provider value={Parse}>
{/* ... */}
</ParseContext.Provider>
)
Поиск и манипулирование данными
В последнем разделе мы будем использовать Parse SDK для аутентификации пользователя и получения информации о нем.
Вместо того чтобы повторять один и тот же код в каждом экране, мы создадим хук useParse
. Этот хук будет получать экземпляр Parse
из контекста, получать информацию о пользователе и запускать обновление, когда все будет готово.
Создайте новый файл с именем useParse.ts в папке контекста:
// context/useParse.ts
import {useContext, useEffect, useState} from "react";
import ParseContext from "@/context/parseContext";
export function useParse() {
const parse = useContext(ParseContext) as typeof Parse;
const [parseUser, setParseUser] = useState<Parse.User | null>(null);
const [isParseLoaded, setIsParseLoaded] = useState(false);
useEffect(() => {
(async () => {
try {
setParseUser(await parse.User.currentAsync());
} catch (e) {
console.error(e);
} finally {
setIsParseLoaded(true);
}
})();
}, []);
return {parse, parseUser, isParseLoaded};
}
Затем измените файл index.tsx, заменив isAuthenticated
на фактическую проверку сессии:
// app/index.tsx
// ...
import {useParse} from "@/hooks/useParse";
export default function IndexScreen() {
const router = useRouter();
const {parse, parseUser, isParseLoaded} = useParse();
useEffect(() => {
if (!isParseLoaded) return;
(async () => {
if (parseUser) {
console.log("User is authenticated!");
console.log(parseUser.toJSON());
router.replace("/profile");
} else {
console.log("User is not authenticated.");
console.log({});
router.replace("/(auth)/login");
}
})();
}, [isParseLoaded]);
return (
// ...
);
}
Затем измените файл login.tsx для входа пользователя в систему:
// app/(auth)/login.tsx
// ...
import {useParse} from "@/hooks/useParse";
export default function LoginScreen() {
const router = useRouter();
const {parse, parseUser, isParseLoaded} = useParse();
// ...
const onLogin = async () => {
// ...
try {
await parse.User.logIn(username, password);
router.push("/(tabs)/profile");
} catch (error: any) {
setError(error.message);
}
}
return (
// ...
);
}
Затем измените register.tsx аналогично login.tsx, но на этот раз замените TODO следующим образом:
// app/(auth)/register.tsx
try {
const user = await parse.User.signUp(username, password, undefined, undefined);
user.setEmail(email);
await user.save();
router.replace("/(tabs)/profile")
} catch (error: any) {
setError(error.message);
}
В последнюю очередь измените файл profile.tsx для отображения информации о профиле:
// app/(tabs)/profile.tsx
// ...
import {useParse} from "@/hooks/useParse";
export default function IndexScreen() {
const router = useRouter();
const {parse, parseUser, isParseLoaded} = useParse();
// ...
useEffect(() => {
if (!parseUser) return;
setBio(parseUser.get("bio") || "");
}, [parseUser]);
const onSave = async () => {
if (!parseUser) return;
parseUser.set("bio", bio);
try {
await parseUser.save();
setSuccess("Bio saved successfully.");
} catch (error: any) {
setError(error.message);
}
}
const onLogout = async () => {
router.replace("/(auth)/login");
await parse.User.logOut();
}
return (
<Container>
{!isParseLoaded ? (
<ActivityIndicator
size="large"
animating={true}
/>
) : (
<>
{/* ... */}
</>
)}
</Container>
);
}
Не забудьте изменить TODO в обратном вызове. Используйте {parseUser!.getUsername()}
и {parseUser!.getEmail()}
.
На этом этапе приложение должно работать полностью. Перезапустите сервер разработки и протестируйте его, создав учетную запись, войдя в систему, выйдя из нее и изменив свою биографию. И наконец, убедитесь, что изменения отразились в базе данных.
Заключение
В заключение, теперь вы знаете, что такое аутентификация, каковы ее преимущества и как она сопоставляется с авторизацией.
Кроме того, вы узнали, как настроить аутентификацию Back4app и интегрировать ее в приложение React Native (на основе Expo).
Будущие шаги
- Узнайте о социальной аутентификации с помощью Google, Facebook и Apple.
- Посмотрите на Back4app Admin App, чтобы получить шикарную панель администрирования в режиме реального времени
Окончательный вариант исходного кода доступен на GitHub.