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 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!

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

相关推荐
杨荧4 分钟前
【开源免费】基于Vue和SpringBoot的实习管理系统(附论文)
java·前端·javascript·vue.js·spring boot·spring cloud·java-ee
软件小伟6 分钟前
Element UI如何实现按需导入--Vue3篇
前端·javascript·ui·elementui·vue
JackieDYH2 小时前
element-plus如何修改内部样式而不影响vue其他组件的样式
前端·javascript·vue.js
且从容.2 小时前
vue下载后端提供的文件/播放音频文件
前端·javascript·vue.js
老码沉思录2 小时前
React Native 全栈开发实战班 - 打包发布之热更新
javascript·react native·react.js
Black蜡笔小新2 小时前
H.265流媒体播放器EasyPlayer.js视频流媒体播放器关于直播流播放完毕是否能监听到
开发语言·javascript·h.265
思考的Joey3 小时前
一种纯前端的H5灰度方案
前端·javascript
Black蜡笔小新3 小时前
H.264/H.265播放器EasyPlayer.js网页直播/点播播放器关于播放的时候就有声音
javascript·h.265·h.264
洋葱土豆和香菜3 小时前
HTML、CSS与JavaScript基础
javascript·css·html