《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);
}
AI 代码解读

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();
}
AI 代码解读

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();
}
AI 代码解读

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();
}
AI 代码解读

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

2.13.5 风险评估

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

2.13.6 相关规范

image

2.13.7 参考书目

image

目录
打赏
0
0
0
0
1408
分享
相关文章
Java 字符串详解
本文介绍了 Java 中的三种字符串类型:String、StringBuffer 和 StringBuilder,详细讲解了它们的区别与使用场景。String 是不可变的字符串常量,线程安全但操作效率较低;StringBuffer 是可变的字符串缓冲区,线程安全但性能稍逊;StringBuilder 同样是可变的字符串缓冲区,但非线程安全,性能更高。文章还列举了三者的常用方法,并总结了它们在不同环境下的适用情况及执行速度对比。
52 17
Java字符串缓冲区
字符串缓冲区是用于处理可变字符串的容器,Java中提供了`StringBuffer`和`StringBuilder`两种实现。由于`String`类不可变,当需要频繁修改字符串时,使用缓冲区更高效。`StringBuffer`是一个线程安全的容器,支持动态扩展、任意类型数据转为字符串存储,并提供多种操作方法(如`append`、`insert`、`delete`等)。通过这些方法,可以方便地对字符串进行添加、插入、删除等操作,最终将结果转换为字符串。示例代码展示了如何创建缓冲区对象并调用相关方法完成字符串操作。
43 13
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
Java爬虫获取微店快递费用item_fee API接口数据实现
本文介绍如何使用Java开发爬虫程序,通过微店API接口获取商品快递费用(item_fee)数据。主要内容包括:微店API接口的使用方法、Java爬虫技术背景、需求分析和技术选型。具体实现步骤为:发送HTTP请求获取数据、解析JSON格式的响应并提取快递费用信息,最后将结果存储到本地文件中。文中还提供了完整的代码示例,并提醒开发者注意授权令牌、接口频率限制及数据合法性等问题。
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
37 4
|
2月前
|
使用Java和Spring Data构建数据访问层
本文介绍了如何使用 Java 和 Spring Data 构建数据访问层的完整过程。通过创建实体类、存储库接口、服务类和控制器类,实现了对数据库的基本操作。这种方法不仅简化了数据访问层的开发,还提高了代码的可维护性和可读性。通过合理使用 Spring Data 提供的功能,可以大幅提升开发效率。
89 21
Java智慧工地(源码):数字化管理提升施工安全与质量
随着科技的发展,智慧工地已成为建筑行业转型升级的重要手段。依托智能感知设备和云物互联技术,智慧工地为工程管理带来了革命性的变革,实现了项目管理的简单化、远程化和智能化。
55 5
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
88 7
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
138 1
|
2月前
|
java怎么统计每个项目下的每个类别的数据
通过本文,我们详细介绍了如何在Java中统计每个项目下的每个类别的数据,包括数据模型设计、数据存储和统计方法。通过定义 `Category`和 `Project`类,并使用 `ProjectManager`类进行管理,可以轻松实现项目和类别的数据统计。希望本文能够帮助您理解和实现类似的统计需求。
132 17