React Native 全栈开发实战班 - 原生功能集成之第三方登录

第三方登录 是指用户使用第三方平台(如 Google、Facebook、Apple、Twitter 等)的账户进行应用登录。这种方式简化了用户注册和登录流程,提高了用户体验,并利用第三方平台提供的身份验证机制来确保安全性。React Native 提供了多种方式来实现第三方登录,包括使用第三方库(如 react-native-google-signin, react-native-facebook-login, react-native-apple-authentication)和调用原生模块。本章节将详细介绍如何使用 react-native-google-signinreact-native-facebook-login 库来实现 Google 和 Facebook 第三方登录。


5.1 第三方登录概述

第三方登录的主要流程包括:

  1. 用户选择第三方平台进行登录: 用户选择使用 Google、Facebook 等第三方平台的账户进行登录。
  2. 应用调用第三方平台的 SDK 进行身份验证: 应用通过第三方平台的 SDK 或 API 发起身份验证请求。
  3. 用户授权: 用户在第三方平台授权应用访问其账户信息。
  4. 获取用户信息: 应用从第三方平台获取用户的身份信息(如用户 ID、姓名、邮箱等)。
  5. 登录完成: 应用根据获取到的用户信息完成登录流程。

常见的第三方登录平台:

  • Google Sign-In
  • Facebook Login
  • Apple Sign-In
  • Twitter Login
  • GitHub Login
  • 微信登录
  • QQ 登录

React Native 提供了多种第三方库来简化第三方登录的实现:

  • react-native-google-signin: 用于实现 Google 登录。
  • react-native-facebook-login: 用于实现 Facebook 登录。
  • react-native-apple-authentication: 用于实现 Apple 登录。
  • react-native-twitter-signin: 用于实现 Twitter 登录。
  • react-native-wechat: 用于实现微信登录。

本章节将重点介绍如何使用 react-native-google-signinreact-native-facebook-login 库来实现 Google 和 Facebook 第三方登录。


5.2 使用 react-native-google-signin 实现 Google 登录

react-native-google-signin 是一个流行的第三方库,用于实现 Google 登录功能。

5.2.1 安装 react-native-google-signin
bash 复制代码
npm install @react-native-google-signin/google-signin

链接原生依赖(React Native 0.60 及以上版本自动链接):

bash 复制代码
cd ios
pod install
cd ..
5.2.2 配置 Google API
  1. 创建 Google Cloud 项目:

    前往 Google Cloud Console,创建一个新项目。

  2. 启用 Google Sign-In API:

    在 API 库中,启用 Google Sign-In API。

  3. 配置 OAuth 同意屏幕:

    配置 OAuth 同意屏幕,设置应用名称、支持邮箱等。

  4. 创建 OAuth 2.0 客户端 ID:

    在凭据页面,创建一个 OAuth 客户端 ID,选择 Android 或 iOS 平台,并填写应用包名和 SHA-1 指纹。

  5. 配置 google-services.jsonGoogleService-Info.plist

    下载 google-services.json 文件,并将其放置在 android/app 目录下。

    下载 GoogleService-Info.plist 文件,并将其添加到 Xcode 项目中。

5.2.3 基本用法

示例:

javascript 复制代码
import React from 'react';
import { View, Button, StyleSheet, Alert } from 'react-native';
import { GoogleSignin, GoogleSigninButton, statusCodes } from '@react-native-google-signin/google-signin';

const GoogleLoginExample = () => {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    // 配置 Google Sign-In
    GoogleSignin.configure({
      webClientId: 'YOUR_WEB_CLIENT_ID', // 从 Google API Console 获取
      offlineAccess: true, // 是否支持离线访问
      hostedDomain: '', // 指定域名(可选)
      forceCodeForRefreshToken: true, // 是否强制刷新 token
      accountName: '', // 指定账户名(可选)
    });
  }, []);

  const handleSignIn = async () => {
    try {
      await GoogleSignin.hasPlayServices();
      const userInfo = await GoogleSignin.signIn();
      setUser(userInfo);
      console.log('用户信息:', userInfo);
    } catch (error) {
      if (error.code === statusCodes.SIGN_IN_CANCELLED) {
        console.log('用户取消登录');
      } else if (error.code === statusCodes.IN_PROGRESS) {
        console.log('登录操作正在进行中');
      } else {
        console.error('登录错误:', error);
      }
    }
  };

  const handleSignOut = async () => {
    try {
      await GoogleSignin.signOut();
      setUser(null);
      console.log('用户已登出');
    } catch (error) {
      console.error('登出错误:', error);
    }
  };

  return (
    <View style={styles.container}>
      {user ? (
        <View>
          <Text style={styles.text}>Hello, {user.user.name}</Text>
          <Button title="登出" onPress={handleSignOut} />
        </View>
      ) : (
        <GoogleSigninButton
          style={styles.button}
          size={GoogleSigninButton.Size.Wide}
          color={GoogleSigninButton.Color.Dark}
          onPress={handleSignIn}
        />
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  button: {
    width: 200,
    height: 50,
  },
  text: {
    fontSize: 18,
    marginBottom: 10,
  },
});

export default GoogleLoginExample;

解释:

  • GoogleSignin.configure 方法: 配置 Google Sign-In,包括 webClientId(从 Google API Console 获取)。
  • GoogleSignin.hasPlayServices 方法: 检查设备是否安装了 Google Play 服务。
  • GoogleSignin.signIn 方法: 发起 Google 登录请求。
  • GoogleSignin.signOut 方法: 登出用户。
5.2.4 获取用户信息

react-native-google-signin 返回的用户信息包含以下字段:

  • id: 用户唯一标识符。
  • name: 用户姓名。
  • email: 用户邮箱。
  • photo: 用户头像 URL。
  • idToken: 身份验证 token。
  • accessToken: 访问 token。

示例:

javascript 复制代码
const handleSignIn = async () => {
  try {
    await GoogleSignin.hasPlayServices();
    const userInfo = await GoogleSignin.signIn();
    console.log('用户信息:', userInfo);
    // 发送用户信息到服务器进行身份验证
  } catch (error) {
    // 处理错误
  }
};
5.2.5 处理登录状态

可以通过 isSignedIn 方法检查用户是否已经登录。

示例:

javascript 复制代码
const checkLoginStatus = async () => {
  const isSignedIn = await GoogleSignin.isSignedIn();
  if (isSignedIn) {
    const userInfo = await GoogleSignin.signInSilently();
    setUser(userInfo);
  }
};

5.3 使用 react-native-facebook-login 实现 Facebook 登录

react-native-facebook-login 是一个流行的第三方库,用于实现 Facebook 登录功能。

5.3.1 安装 react-native-facebook-login
bash 复制代码
npm install react-native-facebook-login

链接原生依赖(React Native 0.60 及以上版本自动链接):

bash 复制代码
cd ios
pod install
cd ..
5.3.2 配置 Facebook API
  1. 创建 Facebook 应用:

    前往 Facebook Developers,创建一个新应用。

  2. 配置 OAuth 重定向 URI:

    在 Facebook 应用设置中,配置 OAuth 重定向 URI。

  3. 配置 Info.plist(iOS):

    Info.plist 文件中添加以下内容:

    xml 复制代码
    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>fbYOUR_FB_APP_ID</string>
        </array>
      </dict>
    </array>
    <key>FacebookAppID</key>
    <string>YOUR_FB_APP_ID</string>
    <key>FacebookDisplayName</key>
    <string>YOUR_APP_NAME</string>
  4. 配置 AndroidManifest.xml(Android):

    AndroidManifest.xml 文件中添加以下内容:

    xml 复制代码
    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>

    res/values/strings.xml 文件中添加:

    xml 复制代码
    <string name="facebook_app_id">YOUR_FB_APP_ID</string>
5.3.3 基本用法

示例:

javascript 复制代码
import React from 'react';
import { View, Button, StyleSheet, Alert } from 'react-native';
import { LoginManager, AccessToken } from 'react-native-facebook-login';

const FacebookLoginExample = () => {
  const handleLogin = () => {
    LoginManager.logInWithPermissions(['public_profile', 'email']).then(
      (result) => {
        if (result.isCancelled) {
          console.log('用户取消登录');
        } else {
          AccessToken.getCurrentAccessToken().then((data) => {
            const token = data.accessToken;
            fetch('https://graph.facebook.com/v12.0/me?fields=id,name,email&access_token=' + token)
              .then((response) => response.json())
              .then((json) => {
                console.log('用户信息:', json);
                // 发送用户信息到服务器进行身份验证
              })
              .catch((error) => {
                console.error('获取用户信息失败:', error);
              });
          });
        }
      },
      (error) => {
        console.error('登录错误:', error);
      }
    );
  };

  const handleLogout = () => {
    // Facebook SDK 不提供直接登出方法
    // 可以清除本地存储的用户信息
    Alert.alert('登出', 'Facebook SDK 不提供直接登出方法');
  };

  return (
    <View style={styles.container}>
      <Button title="Facebook 登录" onPress={handleLogin} />
      <Button title="登出" onPress={handleLogout} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
});

export default FacebookLoginExample;

解释:

  • LoginManager.logInWithPermissions 方法: 发起 Facebook 登录请求,并请求指定权限。
  • AccessToken.getCurrentAccessToken 方法: 获取当前用户的访问 token。
  • fetch 请求: 使用 Graph API 获取用户信息。
5.3.4 获取用户信息

可以通过 Facebook Graph API 获取用户信息,如用户 ID、姓名、邮箱等。

示例:

javascript 复制代码
const getUserInfo = (token) => {
  fetch('https://graph.facebook.com/v12.0/me?fields=id,name,email&access_token=' + token)
    .then((response) => response.json())
    .then((json) => {
      console.log('用户信息:', json);
      // 发送用户信息到服务器进行身份验证
    })
    .catch((error) => {
      console.error('获取用户信息失败:', error);
    });
};
5.3.5 处理登录状态

Facebook SDK 本身不提供直接的登出方法,但可以通过清除应用的登录状态来实现登出功能。以下是如何处理登录状态的详细说明:

5.3.5.1 清除登录状态

要登出用户,通常需要清除应用中的登录状态。由于 react-native-facebook-login 不提供直接的登出方法,可以通过以下几种方式来实现:

  1. 清除 Access Token:

    使用 AccessToken 模块清除存储的 Access Token。

    javascript 复制代码
    import { AccessToken } from 'react-native-facebook-login';
    
    const handleLogout = async () => {
      try {
        await AccessToken.setCurrentAccessToken(null);
        Alert.alert('登出成功', '您已成功登出 Facebook');
      } catch (error) {
        console.error('登出失败:', error);
        Alert.alert('登出失败', '无法清除登录状态');
      }
    };

    解释:

    • AccessToken.setCurrentAccessToken(null) 方法用于清除存储的 Access Token。
    • 清除 Token 后,应用将认为用户已登出。
  2. 清除应用缓存(可选):

    有时,清除 Access Token 可能不足以完全登出用户,尤其是在应用缓存中仍然保留用户信息的情况下。此时,可以选择清除应用的缓存。

    javascript 复制代码
    import { AsyncStorage } from 'react-native';
    
    const clearAppCache = async () => {
      try {
        await AsyncStorage.clear();
        console.log('应用缓存已清除');
      } catch (error) {
        console.error('清除缓存失败:', error);
      }
    };
    
    const handleLogout = async () => {
      try {
        await AccessToken.setCurrentAccessToken(null);
        await clearAppCache();
        Alert.alert('登出成功', '您已成功登出 Facebook');
      } catch (error) {
        console.error('登出失败:', error);
        Alert.alert('登出失败', '无法清除登录状态');
      }
    };

    解释:

    • AsyncStorage.clear() 方法用于清除应用的所有存储数据,包括缓存的用户信息。
  3. 调用 Facebook SDK 的登出(高级):

    如果需要更彻底的登出,可以调用 Facebook SDK 的原生登出方法。这需要使用原生代码进行扩展。

    示例(iOS):

    objective-c 复制代码
    #import <FBSDKLoginKit/FBSDKLoginKit.h>
    
    // 在 AppDelegate.m 中添加一个方法
    - (void)logoutFacebook {
      [[FBSDKLoginManager new] logOut];
    }

    然后在 React Native 中通过原生模块调用这个方法。

    示例(JavaScript):

    javascript 复制代码
    import { NativeModules } from 'react-native';
    
    const { RNFacebookLogin } = NativeModules;
    
    const handleLogout = async () => {
      try {
        await AccessToken.setCurrentAccessToken(null);
        RNFacebookLogin.logoutFacebook();
        Alert.alert('登出成功', '您已成功登出 Facebook');
      } catch (error) {
        console.error('登出失败:', error);
        Alert.alert('登出失败', '无法清除登录状态');
      }
    };

    注意: 这种方法需要使用原生代码进行扩展,适用于高级用户。

5.3.5.2 检查登录状态

可以通过 AccessToken.getCurrentAccessToken 方法检查用户是否已经登录。

示例:

javascript 复制代码
import React, { useEffect, useState } from 'react';
import { View, Text, Button, StyleSheet, Alert } from 'react-native';
import { AccessToken } from 'react-native-facebook-login';

const FacebookLoginExample = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userInfo, setUserInfo] = useState(null);

  useEffect(() => {
    const checkLoginStatus = async () => {
      const token = await AccessToken.getCurrentAccessToken();
      if (token) {
        setIsLoggedIn(true);
        fetchUserInfo(token.accessToken);
      }
    };
    checkLoginStatus();
  }, []);

  const fetchUserInfo = async (token) => {
    try {
      const response = await fetch(`https://graph.facebook.com/v12.0/me?fields=id,name,email&access_token=${token}`);
      const json = await response.json();
      setUserInfo(json);
      console.log('用户信息:', json);
    } catch (error) {
      console.error('获取用户信息失败:', error);
    }
  };

  const handleLogin = () => {
    // 登录逻辑
  };

  const handleLogout = async () => {
    try {
      await AccessToken.setCurrentAccessToken(null);
      await clearAppCache();
      setIsLoggedIn(false);
      setUserInfo(null);
      Alert.alert('登出成功', '您已成功登出 Facebook');
    } catch (error) {
      console.error('登出失败:', error);
      Alert.alert('登出失败', '无法清除登录状态');
    }
  };

  const clearAppCache = async () => {
    try {
      await AsyncStorage.clear();
      console.log('应用缓存已清除');
    } catch (error) {
      console.error('清除缓存失败:', error);
    }
  };

  return (
    <View style={styles.container}>
      {isLoggedIn ? (
        <View>
          <Text style={styles.text}>Hello, {userInfo.name}</Text>
          <Button title="登出" onPress={handleLogout} />
        </View>
      ) : (
        <Button title="Facebook 登录" onPress={handleLogin} />
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  text: {
    fontSize: 18,
    marginBottom: 10,
  },
});

export default FacebookLoginExample;

解释:

  • 检查登录状态: 通过 AccessToken.getCurrentAccessToken 方法检查用户是否已经登录。
  • 获取用户信息: 如果用户已登录,可以通过 Graph API 获取用户信息。
  • 登出: 调用 AccessToken.setCurrentAccessToken(null) 清除 Access Token,并通过 clearAppCache 清除应用缓存。

5.3.5.3 注意事项

  • 权限管理: 在请求用户信息时,需要确保请求的权限(如 email, public_profile)已获得用户授权。
  • 错误处理: 处理可能的错误,如网络错误、权限被拒绝等。
  • 安全性: 确保 Access Token 的安全,避免泄露。

5.4 总结

本章节介绍了 React Native 中的第三方登录功能,包括如何使用 react-native-google-signinreact-native-facebook-login 库来实现 Google 和 Facebook 登录,以及如何处理登录状态和用户信息。通过合理使用第三方登录,可以简化用户注册和登录流程,提高用户体验。


课后作业

  1. 实现一个包含 Google 和 Facebook 登录功能的应用。
  2. 获取并显示用户信息,如用户姓名和邮箱。
  3. 实现登出功能,清除用户登录状态。
  4. 阅读 react-native-google-signinreact-native-facebook-login 官方文档,深入了解其他高级功能和最佳实践。

作者简介

前腾讯电子签的前端负责人,现 whentimes tech CTO,专注于前端技术的大咖一枚!一路走来,从小屏到大屏,从 Web 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!

温馨提示:可搜老码小张公号联系导师

相关推荐
我命由我123454 小时前
React Router 6 - 编程式路由导航、useInRouterContext、useNavigationType
前端·javascript·react.js·前端框架·html·ecmascript·js
橙露5 小时前
JavaScript 异步编程:Promise、async/await 从原理到实战
开发语言·javascript·ecmascript
我命由我123456 小时前
React Router 6 - 嵌套路由、路由传递参数
前端·javascript·react.js·前端框架·html·ecmascript·js
十六年开源服务商6 小时前
2026年WordPress网站地图完整指南
java·前端·javascript
英俊潇洒美少年7 小时前
MessageChannel 如何实现时间切片
javascript·react.js·ecmascript
技术钱8 小时前
react数据大屏四种适配方案
javascript·react.js·ecmascript
李明卫杭州8 小时前
JavaScript 严格模式下 arguments 的区别
前端·javascript
一次旅行9 小时前
今日心理学知识分享(三)
开发语言·javascript·程序人生·ecmascript
牛十二9 小时前
openclaw安装mcporter搜索小红书
开发语言·javascript·ecmascript
小金鱼Y9 小时前
🔥 前端人必看:浏览器安全核心知识点全解析(XSS/CSRF/DDoS)
前端·javascript·安全