You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cloud Function配置allAuthenticatedUsers是否正确?求Perl客户端认证方案

你的配置思路是完全正确的!

先给你吃个定心丸:你当前的配置方向完全符合需求:

  • 启用Firebase Auth的「Email/password」和「Google」认证提供商,让用户可以通过两种常用方式在你的Firebase项目下完成身份认证;
  • 给send_push函数设置allAuthenticatedUsers权限、移除allUsers,确保只有经过Firebase Auth认证的用户才能调用函数——这正好匹配你「允许任何使用自身凭证登录Google的用户调用」的目标(用户通过Google账号登录到你的Firebase Auth后,就属于allAuthenticatedUsers范畴)。

唯一需要明确的细节:这里的「Google登录用户」需要先在你的Firebase Auth系统中完成首次关联登录(首次使用时授权一次即可),因为allAuthenticatedUsers特指你的Firebase项目下的认证用户,而非完全任意的未关联Google账号,但这个流程对用户来说非常轻量化,不会有额外负担。


Perl脚本端的实现方案(无需gcloud)

因为用户没有安装gcloud,我们可以直接通过Firebase Auth的REST API + Perl常用库来实现登录、令牌生成与刷新,完全不需要依赖gcloud工具。下面分两种登录方式给你具体方案:

必备依赖库

首先确保你的Perl环境安装了这些常用库(可以通过cpanm安装):

  • LWP::UserAgent 或 HTTP::Tiny:处理HTTP请求
  • JSON 或 Cpanel::JSON::XS:解析/生成JSON数据
  • Net::OAuth2::Client:(仅Google登录需要)处理OAuth2授权流程

你需要提前从Firebase控制台获取两个关键信息:

  1. 项目的Web API Key(在「项目设置」→「一般」标签页)
  2. 项目的Google OAuth2客户端ID(在「项目设置」→「OAuth客户端」,创建一个「桌面应用」类型的客户端,这样不需要客户端密钥也能工作)

方案1:邮箱密码登录(适合已有账号的用户)

直接调用Firebase Auth的密码登录接口,获取ID Token和Refresh Token:

use strict;
use warnings;
use LWP::UserAgent;
use JSON;

# 替换成你的Firebase Web API Key
my $FIREBASE_WEB_API_KEY = "your-web-api-key";
# 替换成你的Cloud Function URL
my $CLOUD_FUNCTION_URL = "https://your-region-your-project.cloudfunctions.net/send_push";

# 提示用户输入凭证
print "请输入登录邮箱: ";
my $email = <STDIN>;
chomp $email;

print "请输入登录密码: ";
my $password = <STDIN>;
chomp $password;

# 1. 调用Firebase Auth登录接口
my $ua = LWP::UserAgent->new;
my $login_response = $ua->post(
    "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=$FIREBASE_WEB_API_KEY",
    Content => encode_json({
        email => $email,
        password => $password,
        returnSecureToken => JSON::true
    }),
    Content_Type => 'application/json'
);

if (!$login_response->is_success) {
    die "登录失败: " . decode_json($login_response->content)->{error}{message};
}

my $login_data = decode_json($login_response->content);
my $id_token = $login_data->{idToken};
my $refresh_token = $login_data->{refreshToken};

# 2. 用ID Token调用Cloud Function
my $cf_response = $ua->post(
    $CLOUD_FUNCTION_URL,
    Authorization => "Bearer $id_token",
    Content => encode_json({
        # 这里放Perl脚本原来的payload内容,比如fcm_token、notification内容等
        fcm_token => "user-device-token",
        title => "测试通知",
        body => "来自Perl脚本的推送"
    }),
    Content_Type => 'application/json'
);

if ($cf_response->is_success) {
    print "推送发送成功!\n";
} else {
    print "推送失败: " . $cf_response->content . "\n";
}

方案2:Google账号登录(适合用Google凭证的用户)

通过OAuth2授权流程让用户授权,获取Google的ID Token,再交换成Firebase的ID Token:

use strict;
use warnings;
use Net::OAuth2::Client;
use LWP::UserAgent;
use JSON;

# 替换成你的Firebase Web API Key和Google OAuth2客户端ID
my $FIREBASE_WEB_API_KEY = "your-web-api-key";
my $GOOGLE_OAUTH_CLIENT_ID = "your-google-oauth-client-id.apps.googleusercontent.com";
my $CLOUD_FUNCTION_URL = "https://your-region-your-project.cloudfunctions.net/send_push";

# 1. 构建OAuth2客户端,生成授权URL
my $client = Net::OAuth2::Client->new(
    $GOOGLE_OAUTH_CLIENT_ID,
    undef, # 桌面应用类型不需要客户端密钥
    site => 'https://accounts.google.com',
    authorize_path => '/o/oauth2/auth',
    access_token_path => '/o/oauth2/token',
    scope => 'openid email' # 只请求必要的权限
)->web_server(redirect_uri => "urn:ietf:wg:oauth:2.0:oob"); # 桌面应用的回调模式

my $auth_url = $client->authorize_url;
print "请在浏览器中打开以下URL,完成Google授权后输入授权码:\n$auth_url\n";
print "授权码: ";
my $auth_code = <STDIN>;
chomp $auth_code;

# 2. 用授权码交换Google的访问令牌和ID Token
my $token = $client->get_access_token($auth_code);
my $google_id_token = $token->param('id_token');

# 3. 用Google的ID Token登录Firebase Auth,获取Firebase的ID Token
my $ua = LWP::UserAgent->new;
my $fb_login_response = $ua->post(
    "https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=$FIREBASE_WEB_API_KEY",
    Content => encode_json({
        postBody => "id_token=$google_id_token&providerId=google.com",
        requestUri => "http://localhost", # 桌面应用可随便填
        returnSecureToken => JSON::true
    }),
    Content_Type => 'application/json'
);

if (!$fb_login_response->is_success) {
    die "Firebase登录失败: " . decode_json($fb_login_response->content)->{error}{message};
}

my $fb_login_data = decode_json($fb_login_response->content);
my $fb_id_token = $fb_login_data->{idToken};
my $fb_refresh_token = $fb_login_data->{refreshToken};

# 4. 调用Cloud Function
my $cf_response = $ua->post(
    $CLOUD_FUNCTION_URL,
    Authorization => "Bearer $fb_id_token",
    Content => encode_json({
        fcm_token => "user-device-token",
        title => "Google登录用户的推送",
        body => "来自Perl脚本的通知"
    }),
    Content_Type => 'application/json'
);

print $cf_response->is_success ? "推送发送成功!\n" : "推送失败: " . $cf_response->content . "\n";

令牌刷新(ID Token有效期1小时)

ID Token过期后,可以用Refresh Token获取新的ID Token,避免用户重复登录:

# 刷新ID Token的函数
sub refresh_id_token {
    my ($refresh_token, $api_key) = @_;
    my $ua = LWP::UserAgent->new;
    my $response = $ua->post(
        "https://securetoken.googleapis.com/v1/token?key=$api_key",
        Content => encode_json({
            grant_type => "refresh_token",
            refresh_token => $refresh_token
        }),
        Content_Type => 'application/json'
    );
    return decode_json($response->content)->{id_token} if $response->is_success;
    die "令牌刷新失败: " . decode_json($response->content)->{error}{message};
}

# 使用示例
# my $new_id_token = refresh_id_token($fb_refresh_token, $FIREBASE_WEB_API_KEY);

内容的提问来源于stack exchange,提问作者user1361529

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:17:48