《Java安全编码标准》一2.13 IDS12-J在不同的字符编码中无损转换字符串数据

    xiaoxiao2022-06-23  167

    2.13 IDS12-J在不同的字符编码中无损转换字符串数据

    在String对象之间进行转换时,如果涉及不同的编码类型,可能会导致数据丢失。根据Java API[API 2006] 对?String.getBytes(Charset)方法的描述:该方法总会替代那些错误格式的输入和不可映射的字符序列,把它们替换成这些字符的字节数组。当必须将一个String转化为字节数组时,例如写入一个文件,并且在这个字符串中含有不可映射的字符序列的时候,就必须进行正确的字符编码。

    2.13.1 不符合规则的代码示例

    当String包含那些指定在charset中不能正常表示的字符时,这个不符合规则的代码示例[Hornig 2007]会破坏数据。

    // Corrupts data on errors public static byte[] toCodePage_bad(String charset, String string) ??throws UnsupportedEncodingException { ??return string.getBytes(charset); } // Fails to detect corrupt data public static String fromCodePage_bad(String charset, byte[] bytes) ??throws UnsupportedEncodingException { ??return new String(bytes, charset); }

    2.13.2 符合规则的方案

    java.nio.charset.CharsetEncoder类可以将一个16位的Unicode字符转换为指定Charset的一组字节数据。java.nio.charset.Character-Decoder用来完成相反的过程[API 2006]。具体的详情可以参考规则FIO11-J。这个方案[Hornig 2007]使用了CharsetEncoder?和?CharsetDecoder两个类来处理编码转换问题。

    public static byte[] toCodePage_good(String charset, String string) ??throws IOException { ?? ??Charset cs = Charset.forName(charset); ??CharsetEncoder coder = cs.newEncoder(); ??ByteBuffer bytebuf = coder.encode(CharBuffer.wrap(string)); ??byte[] bytes = new byte[bytebuf.limit()]; ??bytebuf.get(bytes); ??return bytes; } public static String fromCodePage_good(String charset,byte[] bytes) ??throws CharacterCodingException { ?? ??Charset cs = Charset.forName(charset); ??CharsetDecoder coder = cs.newDecoder(); ??CharBuffer charbuf = coder.decode(ByteBuffer.wrap(bytes)); ??return charbuf.toString(); }

    2.13.3 不符合规则的代码示例

    这个代码示例[Hornig 2007]想要将一个字符串以特殊的编码方式附加到一个文本文件上,但这样会导致错误,因为String中可能包含无法正确表示的字符。

    // Corrupts data on errors public static void toFile_bad(String charset, String filename, ??????????????????????????????String string) throws IOException { ?? ??FileOutputStream stream = new FileOutputStream(filename, true); ??OutputStreamWriter writer = new OutputStreamWriter(stream, charset); ??writer.write(string, 0, string.length()); ??writer.close(); }

    2.13.4 符合规则的方案

    这个方案[Hornig 2007]使用CharsetEncoder?类来完成所需要的功能。

    public static void toFile_good(String filename, String string, ??????????????????????????????????????String charset) throws IOException { ?? ??Charset cs = Charset.forName(charset); ??CharsetEncoder coder = cs.newEncoder(); ??FileOutputStream stream = new FileOutputStream(filename, true); ??OutputStreamWriter writer = new OutputStreamWriter(stream, coder); ??writer.write(string, 0, string.length()); ??writer.close(); }

    可以使用FileInputStream?和InputStreamReader对象来从文件中读取数据。这个InputStreamReader对象接受可选的CharsetDecoder作为参数,但这个参数必须和前面写入文件时保持一致。

    2.13.5 风险评估

    使用非标准化的方法来处理和字符集转换相关的问题,通常会导致数据丢失。

    2.13.6 相关规范

    2.13.7 参考书目


    最新回复(0)