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控制台获取两个关键信息:
- 项目的Web API Key(在「项目设置」→「一般」标签页)
- 项目的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
相关产品推荐
相关产品推荐

