Java:我们通常不希望向用户显示错误堆栈跟踪中的哪些信息?

ggk*_*ath 11 java security stack-trace

我是java的新手,我不熟悉错误堆栈跟踪在抛出并随后显示给我的Web应用程序的最终用户时使用的格式规则.

我对Oracle数据库的经验是错误堆栈包含内部信息,例如模式和过程名称以及行号,虽然对调试很有用,但我希望阻止用户查看.这是一个例子:

java.sql.SQLException : ORA-20011: Error description here
ORA-07894: at "NAME_OF_SCHEMA.PROCEDURE_NAME", line 121
ORA-08932: at line 10
Run Code Online (Sandbox Code Playgroud)

我要向用户显示的字符串是Error description here.我可以使用正则表达式提取此字符串,因为我知道(1)此字符串始终位于第一行,因此我可以提取错误堆栈跟踪的第一行,以及(2)此字符串始终以Error结束开头并以结尾结束这条线.[注意Oracle用户(我不想误导你):以上仅适用于使用RAISE_APPLICATION_ERROR且错误字符串开头的情况Error,否则文本Error不存在].

我对Java的问题是:

(1)您是否有任何潜在的敏感信息,您不希望用户在错误堆栈中看到?如果是这样,什么?例如,文件路径,服务器名称/ IP等.

(2)我是否可以依赖Java错误堆栈跟踪的格式规则来提取非敏感信息?或者,其他人如何解决这个问题呢?

更新1:

感谢所有回复,他们一直非常有帮助.虽然许多人评论使用诸如getUserFriendlyMessage()将错误映射到有用的用户消息之类的功能,但我想知道是否有人可以扩展此映射.也就是说,对于常见错误(SQL,I/O等),可以使用什么"可靠"标识符来搜索此错误堆栈以识别发生的错误类型,然后推荐相应的文本字符串映射到此错误消息以显示给用户?@ Adarshr的回复是一个好的开始.例如,

Identified Expected   If found in error stack, display this friendly msg to user
-------------------   ----------------------------------------------------------
SQLException          An error occurred accessing the database. Please contact support at support@companyname.com.
IOException           Connection error(?). Please check your internet connection.
Run Code Online (Sandbox Code Playgroud)

假设编译相关的错误不需要解决,而是关注最终用户在正常使用期间可能遇到的错误.作为参考,这是一个运行时错误消息列表:http://mindprod.com/jgloss/runerrormessages.html#IOEXCEPTION

或者,是否可以使用堆栈跟踪的第一行显示给用户?这个链接就像我在上面的原始问题中所获得的那样:

http://www3.ntu.edu.sg/home/ehchua/programming/howto/ErrorMessages.html

例如,如果Exception始终使用标识符,则可以简单地提取介于两者之间的文本Exception和第一行的结尾.我不知道我们是否可以依靠Exception永远在那里.

Ted*_*opp 7

你不应该向你的用户展示任何gobbledygook.它对大多数人来说毫无意义,对你没有帮助.正如您所怀疑的那样,它还暴露了您的实施内部可能暗示恶意用户可能使用的漏洞.

相反,您应该捕获异常,记录异常,并向用户显示更易于理解的错误消息.您可以使用getMessage()提取异常的消息部分.如果异常没有消息,则显示"无可用详细信息"之类的内容.

更新:

我根据问题更新得到了一些评论.首先,我会完全将用户与系统的任何内部隔离,既要善待用户,又要保证安全.(例如,即使知道您正在使用java.sql包,也可能会向聪明的黑客提出漏洞.)因此,在向用户显示任何内容时,请不要使用异常消息,堆栈跟踪的第一行或类似的内容. .

其次,您应该将所有错误从异常级别(在代码中经历它们)映射到处于用户正确抽象级别的消息.正确的方法取决于系统的内部以及用户在引发异常时可能尝试做的事情.这可能意味着将系统结构化为层,以便捕获异常的每个层将其转换为更高抽象层的异常.Java异常可以包装另一个异常(原因).例如:

public boolean copyFile(File source, File destination) throws CopyException {
    try {
        // lots of code
        return true;
    } catch (IOException e) {
        throw new CopyException("File copy failed", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,这可以在User类的更高级别使用:

public boolean shareFile(File source, User otherUser) throws ShareException {
    if (otherUser.hasBlocked(this) {
        throw new ShareException("You cannot share with that user.");
    }
    try {
        return copyFile(source, otherUser.getSharedFileDestination(source));
    } catch (CopyException e) {
        throw new ShareException("Sharing failed due to an internal error", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

(我希望很明显,上面的代码是为了说明将异常转换为更高级别的抽象的想法,而不是作为您应该在系统中使用的代码的建议.)

你想要处理这样的事情(而不是以某种方式按摩消息和/或堆栈跟踪)的原因是异常(例如带有消息"权限被拒绝"的IOException)可能对用户意味着完全不同的事情(并且你的系统)在不同的环境中.


ada*_*shr 5

不要直接向最终用户显示异常消息/ stacktrace.而是尝试使用异常 - 消息映射方法.

例如:

  • SQLException - 抱歉,发生了数据库错误.请稍后再试
  • RuntimeException/ Exception- 抱歉发生了错误.请稍后再试

实际上,您可以使其尽可能通用.也许您可以使用自定义错误代码映射.例如,E0001for SQLException,E0000for Exception等等,并将其显示给最终用户.当他们最终通过错误代码联系客户服务时,这将非常有用.