Flutter中使用Pusher私有频道遇授权问题,求onAuthorizer正确配置
问题背景
使用pusher_channels_flutter包实现实时通知功能,订阅Private频道private-chat.5时,先触发以下错误:
LOG: ERROR: PlatformException(error, Cannot subscribe to a private or presence channel because no Authorizer has been set. Call PusherOptions.setAuthorizer() before connecting to Pusher, null, java.lang.IllegalStateException: Cannot subscribe to a private or presence channel because no Authorizer has been set. Call PusherOptions.setAuthorizer() before connecting to Pusher
添加onAuthorizer函数后,又出现新错误:
LOG: onError: Invalid key in subscription auth data: 'token' code: null exception: null
正确的onAuthorizer返回值说明
onAuthorizer必须返回符合Pusher验证规范的结构,以下是各字段的正确含义与填写方式:
1. auth字段
这是核心签名验证字符串,格式为{你的Pusher API Key}:{HMAC_SHA256签名}。
生成规则:
- 待签名内容为
socket_id:channel_name的拼接字符串 - 使用你的Pusher应用Secret Key作为密钥,通过HMAC-SHA256算法生成签名,再转为十六进制字符串
Dart环境下的生成示例:
import 'dart:convert'; import 'package:crypto/crypto.dart'; String generateAuthSignature(String socketId, String channelName, String secretKey) { final data = '$socketId:$channelName'; final hmac = Hmac(sha256, utf8.encode(secretKey)); final signature = hmac.convert(utf8.encode(data)).toString(); return '你的API Key:$signature'; // 替换为实际API Key }
2. channel_data字段
仅Presence频道需要该字段,Private频道可直接省略。如果是Presence频道,它是一个JSON字符串,必须包含user_id,还可附加用户额外信息:
"{\"user_id\": \"1\", \"user_info\": {\"name\": \"张三\"}}"
3. shared_secret字段
完全不需要返回这个字段,这是你错误添加的冗余键,Pusher的验证响应规范中没有该字段,这也是触发"Invalid key"错误的原因之一。
修正后的onAuthorizer示例
dynamic onAuthorizer(String channelName, String socketId, dynamic options) async { // 替换为你的真实Pusher API Key和Secret Key const apiKey = "你的Pusher API Key"; const secretKey = "你的Pusher Secret Key"; // 生成auth签名 final data = '$socketId:$channelName'; final hmac = Hmac(sha256, utf8.encode(secretKey)); final signature = hmac.convert(utf8.encode(data)).toString(); final auth = '$apiKey:$signature'; // Private频道仅返回auth即可;Presence频道需添加channel_data return { "auth": auth, // 若是Presence频道,取消注释并修改内容 // "channel_data": '{"user_id": "1", "user_info": {"name": "你的用户名"}}' }; }
额外注意事项
- 保持现有代码中
subscribe在前、connect在后的调用顺序 - 不要在返回的Map中添加Pusher规范以外的字段
- 生产环境禁止在客户端硬编码Secret Key,建议通过后端接口获取验证签名,避免密钥泄露
内容的提问来源于stack exchange,提问作者Abdullah Khudher

