停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

最近許多手遊玩家或是特定APP用戶,陸續收到業者公告~「Facebook 登入」10月5日起不再為驗證用戶支援Android 內嵌瀏覽器(WebView),請用戶盡快再設備上安裝Facebook應用程式。

為何臉書不再為驗證用戶支援Android 內嵌瀏覽器? 該如何解決呢? 以下作一說明:

停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

Facebook在Facebook for Developers公告: 從2021 年10 月5 日起,「Facebook 登入」將不再為驗證用戶支援Android 內嵌瀏覽器(WebView)。 如需有關此停用的背景資訊,請參閱部落格文章在Android 內嵌瀏覽器停用「Facebook 登入」驗證的支援。 根據Facebook的說明,此舉主要是要打擊釣魚網站。

停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

由於過去常在網路上看到有些網頁需要登錄帳號才能使用該頁面,當你點下一步的時候,會出現詢問你是否要直接使用Google、Facebook、或綁定其他帳號登錄,但其實是一種網絡釣魚,也被稱為 中間人(MITM)的形式。由於這種方式會收集用戶的帳號密碼資訊,但Facebook很難檢測嵌入式瀏覽器框架,無法從中判斷區別這些平台上的合法登錄和MITM攻擊,所以臉書宣布自10月5日起開始將阻止Android嵌入式瀏覽器框架的登錄,避免用戶遭遇釣魚網站的威脅。

停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

若原本就是用Facebook帳號當作手遊帳戶玩家該怎麼辦呢?

遊戲公司告知的解決對策就是【安裝Facebook】App,這對於台灣玩家問題應該不大,不過對於翻牆來玩國際版的中國玩家恐怕會些麻煩,可能得改用遊戲官方認可的其他帳號了!

停 用 Android 内 嵌 浏览器的 Facebook 登录身份验证 支持

tu0925399900

小丰子,Yahoo奇摩知識家行動通訊的知識長、痞客邦金點賞最佳3C部落客入圍,台灣通訊業的資深老兵。這裡記錄了小丰子對通訊產業與產品的見解、最新3C科技與電信資費訊息,以及一些行銷與管理經驗分享。歡迎一起來Phone言Phone語,並加入小丰子3C俱樂部臉書粉絲專頁。

  • 产品
  • 用例
  • 价格
  • 文档
    • 概览
    • 基础知识
    • 构建
    • 发布与监控
    • 吸引
    • 参考文档
    • 示例
  • 社区
  • 支持
  • 转到控制台

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

您可以将 Facebook 登录机制集成到您的应用中,让您的用户能够使用自己的 Facebook 帐号进行 Firebase 身份验证。

准备工作

  1. 将 Firebase 添加到您的 Android 项目(如果尚未添加)。

  2. 在 Facebook for Developers 网站上,为您的应用获取应用 ID应用密钥
  3. 启用 Facebook 登录机制:
    1. 在 Firebase 控制台中,打开 Auth 部分。
    2. Sign-in method(登录方法)标签页中,启用 Facebook 登录方法,并指定您之前从 Facebook 获得的应用 ID应用密钥
    3. 然后,请务必前往 Facebook for Developers 网站,依次点击 Product Settings(产品设置)> Facebook Login(Facebook 登录)配置,然后在您的 Facebook 应用的设置页面中,确保您的 OAuth 重定向 URI(例如 my-app-12345.firebaseapp.com/__/auth/handler)出现在 OAuth redirect URIs(OAuth 重定向 URI)列表中。
  4. 在您的模块(应用级)Gradle 文件(通常是 <project>/<app-module>/build.gradle)中,添加 Firebase Authentication Android 库的依赖项。我们建议使用 Firebase Android BoM 来实现库版本控制。

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.5.0')
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth'
    }
    

    借助 Firebase Android BoM,可确保您的应用使用的始终是 Firebase Android 库的兼容版本。

    (替代方法) 在不使用 BoM 的情况下添加 Firebase 库依赖项

    如果您选择不使用 Firebase BoM,则必须在每个 Firebase 库的依赖项行中指定相应的库版本。

    请注意,如果您在应用中使用多个 Firebase 库,我们强烈建议您使用 BoM 来管理库版本,从而确保所有版本都兼容。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth:21.0.8'
    }
    

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.5.0')
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx'
    }
    

    借助 Firebase Android BoM,可确保您的应用使用的始终是 Firebase Android 库的兼容版本。

    (替代方法) 在不使用 BoM 的情况下添加 Firebase 库依赖项

    如果您选择不使用 Firebase BoM,则必须在每个 Firebase 库的依赖项行中指定相应的库版本。

    请注意,如果您在应用中使用多个 Firebase 库,我们强烈建议您使用 BoM 来管理库版本,从而确保所有版本都兼容。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx:21.0.8'
    }
    

进行 Firebase 身份验证

  1. 按开发者文档中的说明操作,将 Facebook 登录集成到您的应用中。配置 LoginButtonLoginManager 对象时,请申请 public_profileemail 权限。如果您使用 LoginButton 集成了 Facebook 登录机制,登录 Activity 的代码与以下代码类似:

    Java

    // Initialize Facebook Login button
    mCallbackManager = CallbackManager.Factory.create();
    LoginButton loginButton = findViewById(R.id.button_sign_in);
    loginButton.setReadPermissions("email", "public_profile");
    loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult loginResult) {
            Log.d(TAG, "facebook:onSuccess:" + loginResult);
            handleFacebookAccessToken(loginResult.getAccessToken());
        }
    
        @Override
        public void onCancel() {
            Log.d(TAG, "facebook:onCancel");
        }
    
        @Override
        public void onError(FacebookException error) {
            Log.d(TAG, "facebook:onError", error);
        }
    });
    // ...
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        // Pass the activity result back to the Facebook SDK
        mCallbackManager.onActivityResult(requestCode, resultCode, data);
    }

    Kotlin+KTX

    // Initialize Facebook Login button
    callbackManager = CallbackManager.Factory.create()
    
    buttonFacebookLogin.setReadPermissions("email", "public_profile")
    buttonFacebookLogin.registerCallback(callbackManager, object : FacebookCallback<LoginResult> {
        override fun onSuccess(loginResult: LoginResult) {
            Log.d(TAG, "facebook:onSuccess:$loginResult")
            handleFacebookAccessToken(loginResult.accessToken)
        }
    
        override fun onCancel() {
            Log.d(TAG, "facebook:onCancel")
        }
    
        override fun onError(error: FacebookException) {
            Log.d(TAG, "facebook:onError", error)
        }
    })
    // ...
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
    
        // Pass the activity result back to the Facebook SDK
        callbackManager.onActivityResult(requestCode, resultCode, data)
    }

  2. 在登录 Activity 的 onCreate 方法中,获取 FirebaseAuth 对象的共享实例:

    Java

    private FirebaseAuth mAuth;
    // ...
    // Initialize Firebase Auth
    mAuth = FirebaseAuth.getInstance();

    Kotlin+KTX

    private lateinit var auth: FirebaseAuth
    // ...
    // Initialize Firebase Auth
    auth = Firebase.auth

  3. 初始化 Activity 时,检查用户当前是否已登录:

    Java

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }

    Kotlin+KTX

    public override fun onStart() {
        super.onStart()
        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = auth.currentUser
        updateUI(currentUser)
    }

  4. 用户成功登录之后,在 LoginButtononSuccess 回调方法中为登录的用户获取一个访问令牌,用其换取 Firebase 凭据,然后使用此 Firebase 凭据进行 Firebase 身份验证:

    Java

    private void handleFacebookAccessToken(AccessToken token) {
        Log.d(TAG, "handleFacebookAccessToken:" + token);
    
        AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(TAG, "signInWithCredential:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "signInWithCredential:failure", task.getException());
                            Toast.makeText(FacebookLoginActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                            updateUI(null);
                        }
                    }
                });
    }

    Kotlin+KTX

    private fun handleFacebookAccessToken(token: AccessToken) {
        Log.d(TAG, "handleFacebookAccessToken:$token")
    
        val credential = FacebookAuthProvider.getCredential(token.token)
        auth.signInWithCredential(credential)
                .addOnCompleteListener(this) { task ->
                    if (task.isSuccessful) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success")
                        val user = auth.currentUser
                        updateUI(user)
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInWithCredential:failure", task.exception)
                        Toast.makeText(baseContext, "Authentication failed.",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }
                }
    }

    如果对 signInWithCredential 的调用成功,您可以使用 getCurrentUser 方法获取用户的帐号数据。

后续步骤

在用户首次登录后,系统会创建一个新的用户帐号,并将其与该用户登录时使用的凭据(即用户名和密码、电话号码或者身份验证提供方信息)相关联。此新帐号存储在您的 Firebase 项目中,无论用户采用何种方式登录,您项目中的每个应用都可以使用此帐号来识别用户。

  • 在您的应用中,您可以从 FirebaseUser 对象获取用户的基本个人资料信息。请参阅管理用户。

  • 在您的 Firebase Realtime Database 和 Cloud Storage 安全规则中,您可以从 auth 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

您可以将多个身份验证提供方凭据与一个现有用户帐号关联,让用户可以使用多个身份验证提供方登录您的应用。

如需将用户退出登录,请调用 signOut

Java

FirebaseAuth.getInstance().signOut();

Kotlin+KTX

Firebase.auth.signOut()

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2022-10-15 UTC.

[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"没有我需要的信息" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"太复杂/步骤太多" },{ "type": "thumb-down", "id": "outOfDate", "label":"内容需要更新" },{ "type": "thumb-down", "id": "translationIssue", "label":"翻译问题" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"示例/代码问题" },{ "type": "thumb-down", "id": "otherDown", "label":"其他" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"易于理解" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"解决了我的问题" },{ "type": "thumb-up", "id": "otherUp", "label":"其他" }]