gpt4 book ai didi

java - BufferedReader 的安全实现

转载 作者:行者123 更新时间:2023-11-30 03:27:49 27 4
gpt4 key购买 nike

我想使用 BufferedReader 读取上传到我的服务器的文件。

该文件将被写为 CSV 文件,但我不能假设这一点,因此我编写了一些测试,其中该文件是图像或二进制文件(假设客户端向我发送了错误的文件或攻击者是试图破坏我的服务),或者更糟糕的是,该文件是一个有效的 CSV 文件,但有 100MB 的行。

我的应用程序可以处理这个问题,但它必须读取文件的第一行:

...
String firstLine = bufferedReader.readLine();
//Perform some validations and reject the file if it's not a CSV file
...

但是,当我编写一些测试代码时,我发现了一个潜在的风险:BufferedReader 在找到返回行之前不会对其读取的字节数执行任何控制,因此它最终可能会引发 OutOfMemoryError。

这是我的测试:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import org.junit.Test;

public class BufferedReaderTest {

@Test(expected=OutOfMemoryError.class)
public void testReadFileWithoutReturnLineCharacter() throws IOException {
BufferedReader bf = new BufferedReader(getInfiniteReader());

bf.readLine();

bf.close();
}

private Reader getInfiniteReader() {
return new Reader(){

@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 'A';
}

@Override
public void close() throws IOException {

}
};
}
}

我一直在互联网上查找一些安全的 BufferedReader 实现,但我找不到任何东西。我发现的唯一类是 apache IO 中的 BoundedInputStream,它限制输入流读取的字节数。

我需要一个 BufferedReader 的实现,它知道如何限制每行读取的字节/字符数。

类似这样的事情:

  • 应用调用“readLine()”
  • BufferedReader 读取字节,直到找到返回行字符或达到允许的最大字节数
  • 如果找到返回行字符,则重置读取的字节(以便它可以读取下一行)并返回内容
  • 如果达到允许的最大字节数,则会抛出异常

有人知 Prop 有这种行为的 BufferedReader 的实现吗?

最佳答案

这不是您应该如何继续检测文件是否是二进制文件的方法。

以下是检查文件是否真正为文本的方法;请注意,这要求您事先知道编码:

final Charset cs = StandardCharsets.UTF_8; // or another

final CharsetDecoder decoder = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT); // default is REPLACE!

// Here, "in" is the input stream from the file
try (
final Reader reader = new InputStreamReader(in, decoder);
) {
final char[] buf = new char[4096]; // or other size
while (reader.read(buf) != -1)
; // nothing
} catch (MalformedInputException e) {
// cannot decode; binary, or wrong encoding
}

现在,由于您可以通过 Reader 初始化 BufferedReader,因此您可以使用:

try (
final Reader r = new InputStreamReader(in, decoder);
final BufferedReader reader = new BufferedReader(r);
) {
// Read lines normally
} catch (CharacterCodingException e) {
// Not a CSV, it seems
}

// etc
<小时/>

现在,更多地解释一下它是如何工作的......虽然这是用 Java 阅读文本的基本部分,但它也是同样被根本性误解的部分!

当您使用Reader将文件读取为文本时,您必须指定字符编码;在 Java 中,这是一个 Charset

内部发生的事情是,Java 将从该 Charset 创建一个 CharsetDecoder,读取 byte 流并输出一个 char 流。处理错误的方法有以下三种:

  • CodingErrorAction.REPLACE(默认):不可映射的字节序列被替换为 Unicode replacement character (它确实敲响了警钟,对吧?);
  • CodingErrorAction.IGNORE:不可映射的字节序列不会触发 char 的发射;
  • CodingErrorAction.REPORT:不可映射的字节序列触发抛出CharacterCodingException,它继承IOException;反过来,CharacterCodingException 的两个子类是 MalformedInputExceptionUnmappableCharacterException

因此,为了检测文件是否真正是文本,您需要做的是:

  • 提前了解编码!
  • 使用配置有 CodingErrorAction.REPORTCharsetDecoder
  • InputStreamReader中使用它。

这是一种方式;还有其他的。然而,它们在某些时候都会使用 CharsetDecoder

类似地,还有一个 CharsetEncoder 用于反向操作(char 流到 byte 流),这就是作家家族。

关于java - BufferedReader 的安全实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29769400/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com