如何在 React Native 应用程序中添加身份验证?

身份验证几乎是每个应用程序的核心组件。
这篇实用文章将逐步指导您开始使用 React Native 身份验证。
此外,它还将介绍身份验证的基础知识、与授权的比较、身份验证流程以及使用身份验证的好处。
什么是身份验证?
身份验证是验证某人身份的过程。一般来说,有三种验证方式,一种是通过以下方式进行验证:
- 您知道的东西(如密码、PIN 码)
- 您拥有的东西(如手机、钥匙等)
- 您的身份(如指纹、虹膜)
大多数应用程序使用第一个选项,但也有很多应用程序将多个选项结合起来以提高安全级别。这一概念被称为多因素身份验证(MFA)。
认证流程
通用身份验证流程是这样的
- 用户向服务器发送密码。
- 服务器会对密码进行散列,并与数据库中的密码散列进行比较。
- 如果哈希值匹配,服务器就会创建一个会话,并向用户发送会话令牌。相反,如果哈希值不匹配,则会出现错误。
- 然后,用户在每次请求时都会使用会话令牌。每次请求时,服务器都会检查令牌是否存在且有效。
上述流程就是所谓的令牌身份验证。其他身份验证系统包括JSON 网络令牌(JWT)、基本访问身份验证、社交登录等。
认证与授权
身份验证是验证用户身份的行为,而授权则是验证用户是否有足够的权限执行操作的行为。
授权模式包括强制访问控制(MAC)、自由访问控制(DAC)和基于角色的授权等。
身份验证的好处
让我们来看看在移动应用程序中使用身份验证的一些好处。
安全
身份验证可以保护您的应用程序免遭未经授权的访问,并保证只有合法用户才能访问您的服务。
这有助于防止数据泄露和网络攻击,确保应用程序环境安全可信。
个性化
通过身份验证,可以在应用程序中获得个性化的用户体验。当用户登录时,他们可以访问定制设置、偏好设置和针对其需求的推荐。
这种个性化使应用程序更具吸引力,更方便用户使用。它通过提供更相关、更愉快的体验来留住用户。
法律要求
有些国家的法律要求您核实用户身份。其中一个例子就是 “了解你的客户”(KYC)。
几乎所有金融应用程序都必须这样做。您必须拥有一个适当的身份验证系统,以符合这些规定或保护用户的个人信息。
如何在 React Native 应用程序中添加身份验证?
这部分文章将逐步指导如何在React Native(Expo) 应用程序中添加Back4app身份验证。
先决条件
- 对后台即服务(BaaS)有基本了解
- JavaScript IDE、Node.js 和移动模拟器或实体设备
- 读写 JavaScript 代码的能力
- 具有使用 React Native 和 Expo 的经验
- 免费的 Back4app 账户
什么是 Back4app?
Back4app 是最好的开源后端即服务(BaaS)解决方案之一。它是一个成熟可靠的平台,自 2015 年以来一直存在。
其主要功能包括实时数据库、云代码功能、自动生成 RESTful/GraphQL API 等!
Back4app 有一个易于使用且直观的管理仪表板,还有一个命令行界面 (CLI) 供高级用户使用。
它还为 JavaScript、PHP、Flutter 和 Dart 等最流行的编程语言和框架提供 SDK。
最重要的是,Back4app 提供免费层级。免费层非常适合测试和原型设计,它包括以下内容:
- 每月 25k 申请
- 250 MB 数据存储空间
- 1 GB 数据传输
- 1 GB 文件存储空间
为什么使用 Back4app?
- 支持社交认证
- 为大多数编程语言和框架提供 SDK
- 轻松设置和使用
- 卓越的客户支持
要了解 Back4app 身份验证与 Firebase 身份验证的比较,请查看《React Firebase 身份验证终极指南》。
项目介绍 – React Native 身份验证入门
我们将构建一个使用 Back4app 身份验证的可投入生产的 React Native 应用程序。该应用程序将允许用户注册、登录和管理个人资料。
除此以外,该应用程序还将有两个标签导航,一个供已通过身份验证的用户使用,另一个供未通过身份验证的用户使用。
最终产品将是这样的

开始编码吧
后台(Back4app)
在本节中,我们将创建一个 Back4app 应用程序,扩展默认用户模型,并获取连接后台所需的 API 密钥。
创建应用程序
首先,登录您的Back4app 账户,如果您还没有账户,请创建一个。
登录后,您将被重定向到应用程序列表。单击 “创建新应用程序 “创建新应用程序。

Back4app 平台允许您部署两种类型的应用程序–后端即服务(BaaS)或容器即服务(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) |
+-----------+------------+-----------------------------------------+
然后,用户类还带有一些额外的字段:
+-----------+----------------+--------------------------+----------+
| Data type | Name | Default value | Required |
+-----------+----------------+--------------------------+----------+
| String | username | | yes |
+-----------+----------------+--------------------------+----------+
| String | email | | no |
+-----------+----------------+--------------------------+----------+
| Boolean | emailVerified | false | no |
+-----------+----------------+--------------------------+----------+
| String | password | | yes |
+-----------+----------------+--------------------------+----------+
| Object* | authData | {} | yes |
+-----------+----------------+--------------------------+----------+
默认的 Back4app 用户类可以满足大多数使用情况。不过,对它进行扩展也很容易。为了演示如何扩展,让我们添加一个简历(bio)字段。
首先,点击数据库表上方的 “+ 列 “按钮。

在列创建表单中选择 “字符串 “作为数据类型,将名称设为bio,使其成为必填项,然后点击 “添加”。

很好,你现在知道 Back4app 数据库类如何工作以及如何扩展用户模型了。
应用程序接口密钥
您需要获取应用程序的 API 密钥,以便从前台连接到后台。
要获取它们,请导航至 Back4app 应用程序,选择侧边栏上的 “安全与密钥”。注意 “客户端密钥 “和 “JavaScript 密钥”。

很好,后台就这样了。
前端(React Native)
在本节中,我们将创建 Expo 应用程序,安装组件库,设置导航,处理屏幕,最后连接前台和后台。
创建应用程序
要创建 React Native 应用程序,我们将使用create-expo-app工具。该实用程序可以生成目录结构、配置 TypeScript 等,从而简化 React Native 应用程序的创建过程。
首先,运行以下命令:
npx create-expo-app@latest back4app-expo-auth
cd back4app-expo-auth
如果尚未安装
create-expo-app,该命令也将安装它。
您会发现引导项目的目录结构如下:
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键在安卓模拟器上打开应用程序。或者,你也可以使用 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.tsx文件:
// 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 布局通常包含大量模板代码。我不想用代码淹没这篇文章,所以请从 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 密钥。
像这样在_layout.tsx中初始化 Parse:
// 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()函数,通过在数据库中添加 “Hello, world!”消息来测试与 Back4app 的连接。重启 Expo 服务器并在模拟器中运行应用程序,确保连接正常。

导航到应用程序的数据库视图,检查是否可以看到消息。
如果出现 “Error: crypto.getRandomValues() not supported”(错误:不支持 crypto.getRandomValues())的错误信息。安装以下依赖项:
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 来传递它。
首先,创建一个上下文目录,并在其中放入以下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 管理应用程序,获取高级实时管理面板
最终源代码可在GitHub 上获取。

