Android应用中通过Google Sign-in实现Pub/Sub认证的方案问询
可行,具体实现方案如下
你完全可以用Google Sign-in获取的用户OAuth 2.0凭据替代服务账号的creds.json来认证Pub/Sub客户端,核心是将Sign-in得到的Access Token转换成Pub/Sub SDK能识别的GoogleCredentials,具体步骤和代码修改如下:
1. 确保Google Sign-in请求Pub/Sub权限
在初始化Google Sign-in时,需要添加Pub/Sub的权限Scope,这样获取到的Access Token才有权限访问你的Pub/Sub订阅:
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestEmail() // 保留原有的Gmail相关Scope,同时添加Pub/Sub的权限Scope .requestScopes( Scope(GmailScopes.GMAIL_READONLY), Scope("https://www.googleapis.com/auth/pubsub") ) .build() val googleSignInClient = GoogleSignIn.getClient(context, gso)
2. 用Sign-in的Access Token创建Pub/Sub认证凭据
从已登录的Google账号中获取有效Access Token,将其包装成GoogleCredentials,替换原有的服务账号凭据:
// 获取已登录的用户账号(假设你已完成Sign-in流程) val signedInAccount = GoogleSignIn.getLastSignedInAccount(context) signedInAccount?.let { account -> // 静默刷新获取有效Access Token(自动处理过期逻辑) googleSignInClient.silentSignIn().addOnSuccessListener { signInResult -> val accessToken = signInResult.accessToken ?: return@addOnSuccessListener // 用Access Token创建GoogleCredentials,并指定Pub/Sub的Scope val userCredentials = GoogleCredentials.create( AccessToken(accessToken.tokenValue, Date(System.currentTimeMillis() + 3600 * 1000)) ).createScoped(listOf("https://www.googleapis.com/auth/pubsub")) // 初始化Pub/Sub Subscriber,替换原有的CredentialsProvider val subscriptionName = ProjectSubscriptionName.of("myproject", "my-sub") val subscriber = Subscriber.newBuilder(subscriptionName) { message, ackConsumer -> Log.d("PUBSUB", "收到消息:${message.data.toStringUtf8()}") ackConsumer.ack() // 务必确认消息,避免重复投递 } .setCredentialsProvider { userCredentials } .build() // 启动订阅(建议用生命周期绑定的CoroutineScope,比如viewModelScope,不要用GlobalScope) viewModelScope.launch(Dispatchers.IO) { subscriber.startAsync().awaitRunning() subscriber.awaitTerminated() } }.addOnFailureListener { // 处理Token刷新失败,比如引导用户重新登录 Log.e("PUBSUB_AUTH", "Token刷新失败", it) } }
3. 关键注意事项
- 权限配置:需要在Google Cloud控制台给当前登录的用户(或其所属的Google Workspace账号)授予
Pub/Sub订阅者(roles/pubsub.subscriber)角色,目标是你要订阅的Pub/Sub订阅资源。 - Token过期处理:Access Token默认1小时过期,
silentSignIn()会自动刷新有效Token,但如果用户长时间未使用App,可能需要重新触发Sign-in流程。 - CoroutineScope选择:绝对不要用
GlobalScope,推荐使用viewModelScope(ViewModel中)或lifecycleScope(Activity/Fragment中),避免内存泄漏。 - 消息确认:收到Pub/Sub消息后必须调用
ackConsumer.ack(),否则消息会被重新投递。
内容的提问来源于stack exchange,提问作者Den
相关产品推荐
相关产品推荐

