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

简介: 本节书摘来自华章出版社《Java安全编码标准》一书中的第2章,第2.13节,作者 (美)Fred Long,Dhruv Mohindra,Robert C. Seacord,Dean F. Sutherland,David Svoboda,更多章节内容可以访问云栖社区“华章计算机”公众号查看

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 风险评估

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

2.13.6 相关规范

image

2.13.7 参考书目

image

相关文章
|
17天前
|
Java
Java 字符串分割split空字符串丢失解决方案
Java 字符串分割split空字符串丢失解决方案
|
1月前
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
22 1
|
1月前
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
15 1
|
1天前
|
存储 Java
Java中利用BitMap位图实现海量级数据去重
Java中利用BitMap位图实现海量级数据去重
|
10天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
15 1
|
12天前
|
SQL 安全 Java
Java安全编程:防范网络攻击与漏洞
【4月更文挑战第15天】本文强调了Java安全编程的重要性,包括提高系统安全性、降低维护成本和提升用户体验。针对网络攻击和漏洞,提出了防范措施:使用PreparedStatement防SQL注入,过滤和转义用户输入抵御XSS攻击,添加令牌对抗CSRF,限制文件上传类型和大小以防止恶意文件,避免原生序列化并确保数据完整性。及时更新和修复漏洞是关键。程序员应遵循安全编程规范,保障系统安全。
|
19天前
|
Java
Java练习题-键盘录入字符串实现大小写转换
Java练习题-键盘录入字符串实现大小写转换
20 2
|
21天前
|
存储 安全 Java
Java中实现高效的字符串拼接技术
【4月更文挑战第6天】在Java编程中,字符串拼接是一个常见的操作。然而,由于字符串的不可变性,频繁的拼接操作可能会导致性能问题。本文将探讨Java中实现高效字符串拼接的技术,包括使用StringBuilder类、StringBuffer类以及Java 8中的StringJoiner类。通过对比这些技术的优缺点,我们将为您提供在不同场景下选择合适的字符串拼接方法的建议。
|
28天前
|
Java
java 8 数组转字符串并以逗号分隔
java 8 数组转字符串并以逗号分隔
11 0
|
28天前
|
存储 安全 Java
【Java技术专题】「攻破技术盲区」攻破Java技术盲点之unsafe类的使用指南(打破Java的安全管控— sun.misc.unsafe)
【Java技术专题】「攻破技术盲区」攻破Java技术盲点之unsafe类的使用指南(打破Java的安全管控— sun.misc.unsafe)
37 0