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

XmlBinaryNodeWriter序列化gMSA Unicode密码用于Web服务传输失败

问题:HPC Web服务提交作业时XmlBinaryNodeWriter序列化失败(含gMSA密码)

背景

我们使用Microsoft HPC Pack 2019 SP3 SDK提交HPC作业,HPC原生不支持Active Directory gMSA账户,因此通过AD获取gMSA账户密码。该MSA密码为256字节,以Unicode(UTF16?-.NET显示密码长度为128)表示。

错误现象

当尝试通过HPC Web服务提交包含该密码的作业时,XmlBinaryNodeWriter序列化失败,抛出以下错误:

Exception thrown: 'System.Text.EncoderFallbackException' in mscorlib.dll
Unable to translate Unicode character \uDC33 at index 43 to specified code page.

我们猜测可能是不可显示字符导致序列化失败,已提供部分脱敏的gMSA密码截图。

补充信息

查看调用栈后发现,MSA密码被尝试以UTF8序列化,但实际为UTF16,需要了解如何告知XmlObjectSerializer该字符串为UTF16而非UTF8。


解答

序列化失败的具体原因

错误中的\uDC33是低代理项(Low Surrogate)字符,这类字符无法单独存在,必须与对应的高代理项(High Surrogate)配对才能构成有效的UTF-16代码点。当XmlBinaryNodeWriter尝试将其按UTF-8序列化时,孤立的低代理项不属于合法Unicode字符,编码器无法完成转换,因此抛出EncoderFallbackException。

本质问题是从AD获取的256字节密码数据被错误转换为字符串:直接将UTF-16字节数组当作字符串处理时,可能出现未配对的代理项(比如字节数组长度异常、数据截断/损坏),导致生成的字符串包含无效字符,最终在UTF-8编码环节失败。

解决思路:正确处理gMSA密码的序列化

XmlObjectSerializer默认采用UTF-8编码,且字符串在.NET中本身就是UTF-16字符序列,无法直接指定“字符串是UTF-16”。核心解决方案是避免将密码字节数组当作字符串处理,而是以二进制安全的方式传递:

  1. 将密码字节数组转换为Base64字符串(推荐)
    把原始256字节的密码数据编码为Base64字符串,所有二进制数据会被转换为可安全序列化的ASCII字符,彻底规避无效Unicode代理项问题。示例代码:

    byte[] gmsaPasswordBytes = // 从AD获取的256字节密码数据
    string passwordBase64 = Convert.ToBase64String(gmsaPasswordBytes);
    

    提交作业时传递该Base64字符串,接收端通过Convert.FromBase64String即可还原为原始字节数组。

  2. 清理字符串中的无效代理项(不推荐)
    如果必须传递字符串形式的密码,可在序列化前清理无效代理项,但此操作可能修改原始密码数据导致验证失败:

    string invalidPassword = // 包含无效代理项的密码字符串
    string cleanedPassword = string.Concat(
        invalidPassword.Normalize(NormalizationForm.FormD)
            .Where(c => char.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
    );
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:35:55