gcm出现"internal error: retry receiver class not set yet"

解决GCM推送异常:重写getSenderIds和onRegistered方法
本文详细介绍了在使用GCM进行消息推送时遇到的发送者ID接收不到异常,通过在GCMIntentService中重写getSenderIds和onRegistered方法解决了问题,并分享了解决方案。

在做gcm的时候,会遇到,有时候可以push信息成功,有时候不可以,并且会出现以下senderId接收不到的异常:

12-11 14:07:02.363: E/GCMRegistrar(10954): internal error: retry receiver class not set yet
12-11 14:07:09.023: E/AndroidRuntime(10954): FATAL EXCEPTION: IntentService[GCMIntentService-DynamicSenderIds-4]
12-11 14:07:09.023: E/AndroidRuntime(10954): java.lang.IllegalStateException: sender id not set on constructor
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at com.google.android.gcm.GCMBaseIntentService.getSenderIds(GCMBaseIntentService.java:125)
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at com.google.android.gcm.GCMBaseIntentService.onHandleIntent(GCMBaseIntentService.java:237)
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at android.os.Handler.dispatchMessage(Handler.java:99)
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at android.os.Looper.loop(Looper.java:137)
12-11 14:07:09.023: E/AndroidRuntime(10954): 	at android.os.HandlerThread.run(HandlerThread.java:60)

找了好久原因,也不知道如何解决,最后无意中找到了答案,跟大家分享一下,希望为遇到相同问题的人提供帮助:

解决方案是在GCMIntentService.java中去重写一下getSenderIds和onRegistered这二个方法:

@Override
    protected String[] getSenderIds(Context context) {
        String[] ids = new String[1];
        ids[0] = ConstantUtil.SENDER_ID;
        return ids;
    }

    @Override
    protected void onRegistered(Context context, String regId) {
        Intent intent = new Intent(ConstantUtil.ACTION_ON_REGISTERED);
        intent.putExtra(ConstantUtil.FIELD_REGISTRATION_ID, regId);
        this.mcontext = context;
        context.sendBroadcast(intent);
    }

后来就没有再遇到过这样的异常了.
<think> 我们需要在配置中严格限制TLS 1.2只使用指定的6个GCM套件,TLS 1.3只使用指定的两个套件。 通常,我们可以使用OpenSSL的配置文件或者命令行选项来设置密码套件。 这里我们以OpenSSL为例,因为它是广泛使用的SSL/TLS库,很多服务器软件(如Apache, Nginx)都基于它。 对于TLS 1.2及以下版本,我们可以通过`CipherString`或`Ciphersuites`(注意不同版本的OpenSSL可能有不同的配置方式)来指定。 对于TLS 1.3,由于是独立的密码套件列表,我们需要单独设置。 在OpenSSL 1.1.1及以上版本中,TLS 1.3的密码套件是通过`Ciphersuites`参数设置的,而TLS 1.2及以下则通过`CipherString`设置。 注意:在OpenSSL配置中,多个密码套件之间可以用冒号分隔。 以下是我们需要设置的: TLS 1.2套件(6个): ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 TLS 1.3套件(2个): TLS_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 在OpenSSL配置中,我们可以这样设置(例如在Apache或Nginx的SSL配置中): 对于TLS 1.2及以下:`CipherString`设置为上述6个套件的列表,用冒号分隔。 对于TLS 1.3:`Ciphersuites`设置为上述2个套件的列表,用冒号分隔。 但是请注意,不同的服务器软件配置方式可能不同。 以下以Apache和Nginx为例: 1. Apache配置示例(使用OpenSSL): 在SSL配置部分,添加: ``` SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256 SSLHonorCipherOrder on ``` 对于TLS 1.3,在Apache 2.4.42及以上版本中,可以使用`SSLCipherSuite`来同时设置TLS 1.2和TLS 1.3的密码套件,但需要将TLS 1.3的密码套件单独列出,并且使用`+`号分隔不同TLS版本的密码套件。然而,更简单的方法是使用`SSLConfCmd`指令(Apache 2.4.8以上)来分别设置: ``` SSLConfCmd Ciphersuites TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256 ``` 或者,如果你使用的是Apache 2.4.42及以上,可以直接在`SSLCipherSuite`中同时设置(但注意格式): ``` SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256 ``` 但是这样设置可能会被解释为同时支持TLS1.2和1.3,不过实际上OpenSSL会区分对待。 2. Nginx配置示例: 在`server`块中: ``` ssl_protocols TLSv1.2 TLSv1.3; # 对于TLSv1.3,使用ssl_ciphers配置是无效的(在较新的版本中,nginx使用单独的ssl_ciphers和ssl_conf_command来配置) ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256'; ssl_prefer_server_ciphers on; # 对于TLS 1.3,nginx 1.19.4以上版本支持使用ssl_conf_command设置 ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256; ``` 注意:上面的配置中,我们禁用了SSLv3和TLSv1.0、TLSv1.1,只启用TLSv1.2和TLSv1.3。 但是,不是所有的客户端都支持这些密码套件。因此,请确保你的客户端(尤其是需要支持的客户端)支持这些套件。 另外,如果你使用的是其他软件(如HAProxy、Postfix等),配置方式会有所不同。 为了验证配置,我们可以使用以下命令: openssl s_client -connect <server>:<port> -tls1_2 -cipher <cipher-name> # 测试TLS1.2的某个套件 openssl s_client -connect <server>:<port> -tls1_3 -ciphersuites <cipher-suite> # 测试TLS1.3的某个套件 或者使用在线工具如SSL Labs的SSL Test进行测试。 此外,请注意密钥交换算法(如DHE)需要强大的DH参数,建议至少2048位。可以使用`openssl dhparam`生成。 下面给出一个生成DH参数的示例命令(2048位): ```bash openssl dhparam -out dhparams.pem 2048 ``` 然后在服务器配置中指定该文件(对于Apache:`SSLOpenSSLConfCmd DHParameters dhparams.pem`;对于Nginx:`ssl_dhparam dhparams.pem;`)。 由于问题要求严格白名单,所以只允许这6个TLS1.2套件和2个TLS1.3套件。在配置中,我们只列出了这些套件,并且使用了`SSLHonorCipherOrder`(Apache)或`ssl_prefer_server_ciphers`(Nginx)来优先使用服务器端的顺序,这样更安全。 最后,请确保你的服务器证书和私钥是匹配的,并且证书链完整。 如果你使用的是其他库(如GnuTLS、BoringSSL等),配置方式会不同。 由于你没有指定具体的服务器软件,我提供了常见的Apache和Nginx示例。如果你需要其他软件的配置,请说明。 相关问题: </think> 要严格限制 TLS 1.2 使用指定的 6 个 GCM 套件,同时限制 TLS 1.3 使用指定的 2 个套件,需要在服务器配置中明确设置密码套件列表并禁用其他选项。以下是详细解决方案: ### 核心配置原则 1. **显式声明允许的套件**:通过白名单精确控制 2. **禁用旧协议**:确保不支持 TLS 1.1 及以下版本 3. **强制服务器首选顺序**:优先使用更安全的套件 4. **验证配置**:使用工具测试实际生效情况 ### 示例配置(OpenSSL/NGINX) ```nginx # NGINX 配置示例 server { listen 443 ssl; # 协议控制:仅允许 TLS 1.2-1.3 ssl_protocols TLSv1.2 TLSv1.3; # TLS 1.2 套件白名单(6个指定GCM套件) ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256'; # TLS 1.3 套件白名单(2个指定套件) ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256; # 强制服务器密码套件优先顺序 ssl_prefer_server_ciphers on; # 其他必要参数 ssl_ecdh_curve secp384r1; # 使用更强的椭圆曲线 ssl_dhparam /path/to/dhparam.pem; # 2048位+ DH参数 ... } ``` ### 配置详解 1. **TLS 1.2 套件控制** `ssl_ciphers` 精确列出允许的6个套件: - 冒号分隔的套件列表形成白名单 - OpenSSL 会自动过滤不支持的套件 - 排序决定了优先级(从左到右优先级递减) 2. **TLS 1.3 套件控制** `ssl_conf_command Ciphersuites` 专用于 TLS 1.3: - 仅允许 `TLS_AES_256_GCM_SHA384` 和 `TLS_AES_128_GCM_SHA256` - TLS 1.3 套件与 TLS 1.2 配置相互独立 3. **关键安全参数** - `ssl_prefer_server_ciphers`:强制客户端使用服务器配置的套件顺序 - `ssl_ecdh_curve`:指定高强度椭圆曲线(避免弱曲线) - `ssl_dhparam`:自定义 DH 参数(2048位以上) ### 验证方法 ```bash # 验证 TLS 1.2 套件 openssl s_client -connect yourdomain.com:443 -tls1_2 -cipher ECDHE-RSA-AES256-GCM-SHA384 # 验证 TLS 1.3 套件 openssl s_client -connect yourdomain.com:443 -tls1_3 -ciphersuites TLS_AES_256_GCM_SHA384 # 使用 SSL Labs 全面测试 https://www.ssllabs.com/ssltest/ ``` ### 注意事项 1. 证书必须与套件匹配: - `ECDSA` 套件需要 ECDSA 证书 - `RSA` 套件需要 RSA 证书 2. 现代客户端要求: - 确保不支持 Windows XP 等老旧系统 - Android 4.x 及以下可能无法连接 3. 性能影响: - AES256 比 AES128 多消耗约 40% CPU - 在低性能设备上考虑平衡安全与性能 ### 其他环境配置 **Apache 示例**: ```apache SSLProtocol TLSv1.2 TLSv1.3 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256 SSLProxyCipherSuite TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256 SSLHonorCipherOrder on ``` **HAProxy 示例**: ```haproxy bind :443 ssl ssl-min-ver TLSv1.2 ssl-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256 ciphersuites TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256 ssl-prefer-server-ciphers ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值