2013-03-12 53 views
6

我用下面的方法在我的ASP.NET Web应用程序接收堆栈跟踪异常返回预期的信息:堆栈跟踪/的StackFrame不要在生产环境中

public static void getStackTraceInfo(System.Diagnostics.StackTrace trace) 
{ 
    for (int i = 0; i < trace.FrameCount; i++) 
    { 
     int nLine = trace.GetFrame(i).GetFileLineNumber(); 
     int nCol = trace.GetFrame(i).GetFileColumnNumber(); 
     string methodName = trace.GetFrame(i).GetMethod().Name; 
    } 
} 

try 
{ 
} 
catch(Exception ex) 
{ 
    getStackTraceInfo(new System.Diagnostics.StackTrace(ex, true)); 
} 

它给我全系列/列/方法名称信息,如果我在Visual Studio 2010开发环境中运行它,但是在IIS上的生产环境中,它将返回所有0,并将方法名称作为空字符串。

我是否需要做任何特殊的事情来使它在IIS上工作?

+0

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 – 2013-03-12 17:45:11

+1

这是正确的。除非应用程序在调试模式下编译并且相关的.pdb文件放置在生产中的bin目录中,否则不会获得具有完整调试信息(包括行号)的堆栈跟踪。不是推荐的做法。 – 2013-03-12 17:47:28

+0

如果你的代码在“build”中的“release”模式下,我想你不会得到行号。 – dekdev 2013-03-12 17:48:15

回答

29

如果我在Visual Studio 2010开发环境中运行它,它将为我提供完整的行/列/方法名称信息,但在IIS上的生产环境中,它会返回全0和方法名称作为空字符串。

正确。仔细阅读该类型的名称;那Diagnostics很重要。该名称空间中的类型用于诊断调试环境中的问题。

我是否需要做任何特殊的事情来使它在IIS上工作?

否;您不需要使用诊断工具生产

如果由于某种原因想要在生产环境中使用诊断工具,至少需要将PDB文件推送到生产环境。这可能是一个危险而愚蠢的做法,我们将在下面看到。我建议你不要这么做。

一些问题,你没有问:

什么工具我应该使用以获得在生产环境中的来电者信息?

如果您需要获取方法调用的行号等,您可能应该使用的工具是新的CallerLineNumber和C#5.0中的相关属性。这里有他们一个很好的博客:

http://blog.slaks.net/2011/10/subtleties-of-c-5s-new-callerlinenumber.html

如果您需要获得有关异常的堆栈跟踪信息,你看到的是你会得到什么。

在调试环境中确实堆栈跟踪目标提供了保证,该堆栈跟踪告诉我在当前呼叫从来的?

不是。一个堆栈跟踪不会告诉你你从哪里来的第一个地方。堆栈跟踪告诉你你要去哪里。这很有用,因为你来自哪里和你下一步要去哪里往往有很强的相关性;通常你会回到你来自的地方。

虽然这并非总是如此。 CLR有时会知道下一步该怎么走,而不知道你来自哪里,在这种情况下堆栈跟踪不包含所需的信息。

例如,尾调用优化可以从堆栈中删除帧。内联优化可以使方法调用看起来像调用方法的一部分。 C#5中的异步工作流完全离开“你从哪里来”和“你下一步要去哪里”;异步方法的堆栈跟踪在await告诉你你要去的是下一个await之后继续,而不是你在第一个await之前如何进入该方法。

堆栈痕迹不可靠,所以不要依赖它们。仅将它们用作诊断辅助工具。

为什么在ASP中暴露诊断信息特别危险?

因为攻击者会通过抛出“异常”输入来引起服务器故障。如果这使服务器失效,那么攻击者会很高兴。如果它使服务器保持运行状态,但会向攻击者泄露有关您的源代码的信息,甚至更好。现在他们有更多的信息可用来发起更复杂的攻击。

ASP服务器应该在生产环境中尽可能少地提供诊断信息。您在该生产环境中拥有的调试信息越少,您犯错误的可能性就越小,并将实施细节公开给攻击者。

+0

好点,除了这句话'堆栈跟踪不会告诉你你从哪里来'。它完全告诉你。当然,有些程序可能会对其进行修改,但这对于磨机代码的运行来说太不寻常了。至于将所有这些调试器信息暴露给公众的危险 - 我完全同意。所有这些信息进入一个内部日志,不会被公开。 – ahmd0 2013-03-12 18:10:46

+17

@ ahmd0:当我告诉人们堆栈跟踪的真相时,我感到惊讶。堆栈跟踪包含*返回地址*,该地址不一定是*调用方*的地址。大部分时间都是这样,但不一定是这样,有些情况并非如此。请记住,堆栈的目的是*继续*的具体化,并且延续是关于*未来*,而不是过去*的定义信息。如果你有时可以从延续中推断关于过去的信息,那很好,但这不是它的目的*,所以你不能依赖它。 – 2013-03-12 18:17:11

+2

当然也没有要求继续由堆栈来完成。正如我上面提到的,异步任务的继续由委托和上下文的组合来表示,没有涉及到堆栈,因此了解任务的继续并不能告诉你任务是如何开始的。 – 2013-03-12 18:18:43