asp.net web開發框架,[轉載]針對IIS7以上的ASP.NET網站自定義錯誤頁面與異常日志總結

 2023-12-06 阅读 28 评论 0

摘要:針對IIS7以上的ASP.NET網站自定義錯誤頁面與異常日志總結 汪宇杰 2014-1-11 星期六 02:31 455 Reads?1 Comments 自定義錯誤頁面和異常記錄是個很古老的話題了,但依舊可以讓人爆到現在。在我做了無數次試驗并總結經驗和原則后,寫下本文,已警后人。 本文的

針對IIS7以上的ASP.NET網站自定義錯誤頁面與異常日志總結


自定義錯誤頁面和異常記錄是個很古老的話題了,但依舊可以讓人爆到現在。在我做了無數次試驗并總結經驗和原則后,寫下本文,已警后人。

本文的范圍和限制

  1. 本文僅僅適用于部署在IIS7或以上版本中的ASP.NET 4.0集成模式應用程序。IIS7以上的意思是Windows Server 2008以上服務器適用。我已在WS2012R2,IIS8上測過。
  2. 本文的方法均適用于ASP.NET WebForm和MVC應用程序。

本文針對的問題

  1. 靜態錯誤頁面好還是動態錯誤頁面好?我該如何設計ASP.NET網站錯誤處理?
  2. 我不希望錯誤頁面后面跟上aspxerrorpath=…這個小尾巴。
  3. 我的自定義錯誤頁面在VS里調試是好的,為什么部署到服務器上就出不來了?
  4. 我的自定義錯誤頁面可以正常顯示,但為什么返回的Http狀態碼不正確?
  5. 異常日志該怎樣記錄,有沒有比較好的實踐?

asp.net web開發框架、一、錯誤頁面的選擇

選擇靜態html頁面作為錯誤頁,還是使用.aspx或是MVC View來顯示錯誤頁面好?這個問題許多人的偏好都不一樣。我強烈建議大家用html靜態頁面作為錯誤頁。請看分析:

首先,用動態頁面的人,無非是為了解決三個問題:顯示錯誤摘要、記錄日志、返回正確的狀態碼。但是,動態頁面最大的問題在于,它們本身是要經過ASP.NET和后臺代碼處理的,萬一你的后臺代碼是爆的,或者ASP.NET自己爆了,那你的錯誤頁面一旦被請求,本身就會引發另一個錯誤。而靜態html是不會有這個問題的。至于在MVC里專門建一個ErrorController的做法就更不可取了。MVC是基于ASP.NET之上的,MVC的Controller只能抓MVC自己的錯誤,抓不到ASP.NET的錯誤,意思就是說,當你的錯誤并不在MVC層面上的時候,ErrorController沒有任何用武之地。例如,當你部署的MVC應用程序缺少MVC的dll時候,MVC框架本身都跑不起來,這個錯誤如何去抓?

另外,我認為在一個Internet站點上,絕不應該向訪客顯示任何的錯誤摘要。這是非常不安全的。所以完全沒有必要用動態頁面。

ASPNET程序開發招聘?至于返回正確狀態碼的問題是這樣的:不少小伙伴發現自己的錯誤頁面能夠顯示,但返回的狀態碼是200OK,所以無奈之下用動態頁面,寫上Response.StatusCode = 500這樣的代碼來強擼。這個在稍后的文章里有解決方案,所以不要為了狀態碼而冒險用動態頁面。有的小伙伴會問,我只寫一筆Response.StatusCode=500能有什么風險?呵呵,想想這種情況:404.cshtml,razor引擎的dll不見了……

另外,一個原則是:錯誤頁面應當是獨立的。如果你的靜態頁面要用到圖片和CSS等外部資源,建議嵌入在頁面里邊,做成單文件的,以免顯示錯誤頁面時請求相關資源再次引發異常。小伙伴又要問了,請求個CSS和圖片什么的,腫么會引發異常呢?那你看看這個:resources.axd?image=…,呵呵。

那么用了靜態頁面以后,記錄日志怎么辦呢?正確的方法應該是交給Global.asax中的“Application_Error”事件處理。稍后會有翔解。

二、配置錯誤頁面:customErrors VS httpErrors

javascript錯誤解決方案,首先,錯誤頁面的顯示方式有兩種。如果你打開IIS,會看到兩個配錯誤頁的地方:.NET Error Pages和Error Pages。

站在開發者的角度來說,ASP.NET Section下的“.NET Error Pages”就是web.confg/system.web/customErrors節點。而IIS Section下的”Error Pages”是web.config/system.webServer/httpErrors節點,這個是IIS7以上特有的。

任何在IIS上對這兩處的更改其實都是在修改web.config文件。

ASP和JSP。那么我們該用哪一個來配置自定義錯誤頁呢?我的一個原則是:讓IIS向用戶展示錯誤頁面,而不要依賴于ASP.NET。 猿因如下:

CustomError的問題:

a)? 在默認情況下,CustomError會采用302重定向的方式來展示錯誤頁面,如果客戶端請求了一個404的頁面,那它得到的將會是一個302緊接著一個200OK,對于人類來說這是OK的,畢竟用戶看到了友好的錯誤頁面,但搜索引擎會認為這個不存在的地址是正常的頁面,并把你的404頁面收入搜索結果。并且每次引發錯誤,URL后邊都會跟上aspxerrorpath這個小尾巴,比如:

http://yoursite.com/404.html?aspxerrorpath=/somethingnotexsit

iis錯誤日志在哪查看,b) 在配置了redirectMode=“ResponseRewrite”后,會引發一個問題,09年就有人當bug提交到MS Connect上了,但目前微軟不打算fix這個bug。即該模式在VS自帶的ASP.NET Development Server上是有效的,瀏覽器顯示的是解析后的HTML頁面,而部署到IIS上之后,瀏覽器顯示是raw html,即你的錯誤頁面的HTML代碼。并且該行為不具有確定性,天曉得你的網站換個環境部署又會爆成什么樣。

c)? IIS7以上版本的特殊性:在集成模式下,IIS的錯誤頁面會優先于ASP.NET錯誤頁面,即IIS的默認錯誤頁會覆蓋你配置的CustomErrors頁面,這就是為什么你在VS下調試是好的,部署到服務器上就爆了。

在IIS7之后,取決于你的配置,用戶的請求并不都一定在ASP.NET管線上處理。如果引發異常的地方不在ASP.NET,那就不會顯示CustomErrors的錯誤頁面。

所以,我強烈建議大家用httpErrors節點替代CustomErrors來配置錯誤頁面。

三、File還是ExecuteURL:httpErrors的正確配法

先貼一個正確的配置樣例:是用File配的。

注意兩處地方:

  1. 斜杠是Windows文件路徑的反斜杠“\”而不是網址URL的斜杠“/”
  2. Path不要以“~”或“\”開頭

不要問我為什么,我也不知道,反正這么弄就是好的。

如果你不幸用了ExecuteURL,你會發現URL路徑只能以“/”開頭:

并且你的錯誤頁會返回200OK而不是正確的404、500等錯誤碼。這在我以前的文章里寫過:

http://diaosbook.com/Post/2012/6/24/correct-way-to-implement-custom-error-page-return-statecode-instead-of-http-200

而用File的意思是,當錯誤被爆出來之后,IIS會把目標File,比如404.html的內容,塞到當前的Response流里面,保持Http狀態碼依舊是404。這就是我們想要的。

四、異常日志記錄

文章在一開始就提了個問題,木有了動態頁面,怎么記錄錯誤日志?我的做法是在Global.asax里處理。

Application_Error事件樣例代碼如下:

var exception = HttpContext.Current.Server.GetLastError(); if (null != exception) { // by default 500 var statusCode = (int)HttpStatusCode.InternalServerError; if (exception is HttpException) { statusCode = new HttpException(null, exception).GetHttpCode(); } else if (exception is UnauthorizedAccessException) { // to prevent login prompt in IIS // which will appear when returning 401. statusCode = (int)HttpStatusCode.Forbidden; } if ((LogHttpNotFound && statusCode == 404) || statusCode != 404) { if (null != _loggerFunc) { LoggerFunc(string.Format("ASP.NET Error Captured, Request URL: {0}, Exception:", HttpContext.Current.Request.Url), exception); } } ExceptionInfo = exception.Message; _statusCode = statusCode; }

一個小小的建議是不要記錄404錯誤,因為你的網站在Internet上會被各種搜索引擎、掃描工具和黑客菊爆,有一種攻擊手段是通過字典猜解目錄,返回404就是不存在,返回403就是存在。所以,當你碰到這種無聊黑客的時候,如果記錄了404請求,那你的日志會非常的大……

我記日志用的組件是NLog,配置簡單,使用容易。Log4net這貨已經好久沒更新了。

如果你決定自己設計日志模塊,那要記住兩個原則:

日志模塊本身并不能因為自己爆掉而影響整個系統運行,即任何在日志模塊里的異常不應該向外冒泡。

考慮并發寫日志的情況,日志操作應該是Fire and Forget的,不能讓應用程序等待日志寫入。

五、總結

  1. 采用靜態html頁面作為錯誤頁。
  2. 采用httpErrors配置錯誤頁面,目的是兼容IIS7以上環境、返回正確錯誤碼、去掉aspxerrorpath小尾巴。
  3. 日志記錄寫在Global.asax里,在Application_Error事件中記錄。

轉載于:https://www.cnblogs.com/sherlock99/p/4109035.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/192628.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息