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

Android网约车应用集成Sinch SDK生成JWT时报bad base-64异常求助

异常原因

本次bad base-64异常触发自代码中Base64.decode(appSecret, Base64.DEFAULT)行,核心问题出在Base64编解码的参数配置错误,具体原因如下:

  • 编解码参数冲突:你在调用Base64.encodeToString时同时传入了Base64.DEFAULT、Base64.NO_PADDING、Base64.NO_WRAP三个互斥的标记,Base64.DEFAULT默认启用末尾补全padding、自动添加换行符的特性,和另外两个标记的功能冲突,会输出不符合规范的Base64字符串。
  • 未使用URL安全模式:JWT标准要求使用URL安全的Base64编码(替换+为-、/为_、移除末尾=填充符),Sinch官方发放的appSecret本身也是URL安全的Base64格式,使用Base64.DEFAULT模式解码时无法识别-、_等字符,直接抛出解码异常。
  • 潜在问题:formatDate方法使用本地时区生成日期,而Sinch服务端校验签名时使用UTC时区,时区不一致会导致后续签名校验失败,不属于本次报错的直接原因,但需要同步修复。
修复方案

按照以下步骤修改代码即可解决问题:

  1. 所有Base64编解码操作统一使用标记Base64.NO_PADDING | Base64.NO_WRAP | Base64.URL_SAFE,移除Base64.DEFAULT参数。
  2. 修改formatDate方法的时区为UTC,对齐服务端校验规则。
  3. 显式将UUID对象转为字符串存入payload,避免JSON序列化异常。

修改后的核心代码如下:

public static String create(String appKey, String appSecret, String userId) {
    JSONObject header = new JSONObject();
    JSONObject payload = new JSONObject();
    final long issuedAt = System.currentTimeMillis() / 1000;
    String kid = "hkdfv1-" + formatDate(issuedAt);
    try {
        header.put("alg", "HS256");
        header.put("typ", "JWT");
        header.put("kid", kid);
        payload.put("iss","//rtc.sinch.com/applications/" + appKey);
        payload.put("sub","//rtc.sinch.com/applications/" + appKey + "/users/" + userId);
        payload.put("iat",issuedAt);
        payload.put("exp",issuedAt + 600);
        // 显式调用toString避免序列化异常
        payload.put("nonce", UUID.randomUUID().toString());
    } catch (JSONException e) {
        throw new RuntimeException(e.getMessage(), e.getCause());
    }

    String headerStr = header.toString().trim().replace("\\/","/");
    String payloadStr = payload.toString().trim().replace("\\/","/");
    // 统一Base64标记
    int base64Flag = Base64.NO_PADDING | Base64.NO_WRAP | Base64.URL_SAFE;
    String headerBase64 = Base64.encodeToString(headerStr.getBytes(), base64Flag);
    String payloadBase64 = Base64.encodeToString(payloadStr.getBytes(), base64Flag);

    String jwtToSign = headerBase64 + "." + payloadBase64;

    String jwtSignature;
    try {
        // 解码appSecret使用相同标记
        byte[] origKey = Base64.decode(appSecret, base64Flag);
        byte[] signingKey = deriveSigningKey(origKey, issuedAt);
        final byte[] macData = Hmac.hmacSha256(signingKey, jwtToSign);
        String signature = Base64.encodeToString(macData, base64Flag);
        jwtSignature = jwtToSign + "." + signature;
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e.getCause());
    }
    return jwtSignature;
}

private static String formatDate(long time) {
    String format = "yyyyMMdd";
    SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
    // 改为UTC时区对齐服务端校验规则
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    return sdf.format(new Date(time * 1000));
}

private static byte[] deriveSigningKey(byte[] key, long issuedAt) {
    return Hmac.hmacSha256(key, formatDate(issuedAt));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:57:05