解決 ASP.NET 跑在 x64 機器上無法連接 Oracle DB 的問題

今天又解決一個十分棘手的問題,我們有個專案原本在 x86 機器上開發 ( 資料庫採用 Oracle ),最近由於主機升級到 Windows 7 (x64) 後發現程式出問題,當在 Visual Studio 中按下 F5 進行測試除錯時完全無法連接到資料庫,而且一整個很沒道理,看看我如何解決這個棘手的問題吧。

我遇到的錯誤如下:

ORA-12154: TNS: 無法解析指定的連線 ID
ORA-12154:TNS:could not resolve service name

錯誤發生點是在「建立連線」的程式碼,只要 Open Connection 就會立即出錯。

這問題首先是出在我同事的身上,他主機在一個多月前換成 Windows Server 2008 (x64),而我是最近才換到 Windows 7 (x64),問題跟他一模一樣,因此也花了好多時間研究分析,直到剛剛跟黑大討論一番後終於給我找出解法。

先說說我電腦的安裝步驟與執行環境:

  • 安裝 Oracle Database 10g Client Release 2 (10.2.0.1.0) for Microsoft Windows (32-bit)
  • 設定 TNSNAMES.ORA 設定檔 ( 100% 肯定設定沒問題 )
  • 使用 SQL Plus 可以正常連線
  • 使用 SQL Developer 可以正常連線
  • 在 Visual Studio 中可以建置(Build)專案,建置/編譯後的組件部署到測試機也都沒問題
  • 在 Visual Studio 中使用內建的 ASP.NET 開發伺服器進行測試
  • 利用 Process Explorer 查看 WebDev.WebServer.EXE 程式,載入的組件都沒問題 (正確載入)
  • 利用 Prcoess Monitor 查看 WebDev.WebServer.EXE 程式,載入的 Oracle Client 相關參數檔路徑也都正確無誤

想破頭無法解決時,黑大建議我用最簡單的方式測試資料庫連線 (如下範例),雖然我自己已經測試數十遍了,但我還是不鐵齒,聽話的再測一次 ( 魔鬼總在細節裡 ):

using (OracleConnection cn = new OracleConnection(
    "Data Source=MyName;" +
    "Persist Security Info=True;" + 
    "User ID=user;" +
    "Password=pass"))
{
    cn.Open(); // 在此發生【 ORA-12154: TNS: 無法解析指定的連線 ID 】的錯誤
}

這時我才想到將 TNSNAME 的完整定義移到這裡試試看,請看如下範例:

using (OracleConnection cn = new OracleConnection(
    "Data Source=" +
    "  (DESCRIPTION =" +
    "    (ADDRESS_LIST =" +
    "      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.245)(PORT = 1521))" +
    "    )" +
    "    (CONNECT_DATA =" +
    "      (SERVICE_NAME = MyName)" +
    "    )" +
    "  )" +
    ";Persist Security Info=True;User ID=user;Password=pass"))
{
    cn.Open(); // 在此時發生【 ORA-6413: 連線未被開啟 】的錯誤
}

這就神奇啦,錯誤訊息竟然不一樣,,中英文錯誤訊息如下:

ORA-6413: 連線未被開啟
ORA-06413: Connection not open

多一條錯誤訊息就多一條線索,對追 Code 絕對有幫助。 ( 好像在玩偵探遊戲一樣 ^^ )

這時就被我搜出一篇文章 ORA-06413: Connection not open. 答案就在其中,原來錯誤發生的原因原來是我的 ASP.NET 開發伺服器 ( WebDev.WebServer.EXE ) 執行檔的路徑有特殊字元導致:

C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\9.0\WebDev.WebServer.EXE

就是這該死的 (x86) 出現在路徑中,導致我的 ASP.NET 怎樣都無法連線到程式,為了驗證確定就是這問題,我試著利用 Process Explorer 找出 WebDev.WebServer.EXE 的啟動參數:

 利用 Process Explorer 找出 WebDev.WebServer.EXE 的啟動參數

並重新透過 cmd.exe (命令提示字元) 啟動 WebDev.WebServer.EXE,這時故意用「短目錄」啟動 ASP.NET 開發伺服器,如下指令:

"C:\PROGRA~2\Common Files\Microsoft Shared\DevServer\9.0\WebDev.WebServer.EX
E"  /port:5970 /path:"D:\XXXX\XXX\Website" /vpath:"/"

神奇的事這就樣發生,Oracle 資料庫竟然真的連上了!!

我的解決之道

  1. 改用 Windows 7 內建的 IIS7 進行網站執行與偵錯,不用 ASP.NET 開發伺服器了。Windows 7 內建的 IIS7 可新增多個網站,管理上也頗方便,不像 Windows XP 只能新增一個網站
  2. 改用 Visual Studio 巨集啟動 ASP.NET 開發伺服器偵錯,細節可參考我的另一篇文章:啟動 ASP.NET 偵錯模式的另一種比按下 F5 還快的方式

本次除錯心得

  • 不要鐵齒,越覺得不可能發生的地方越有可能是破案的核心關鍵!
  • 找個人聊聊你所遇到的錯誤,在互動、對話的過程中也許會想到一些你不曾想到的地方。
  • 「程式除錯」不但要有「經驗」更要有「創意」,當你擁有更多的「生活體驗」(程設的生活),相對的創意也就越多。
  • 熟悉多種除錯工具,並在工具間交互比對、驗證錯誤,一定可以看出一些端倪,但不要只是會「用」工具而已,而是要熟悉工具「背後的原理」,這樣才有助於你思考問題的本質問題背後的問題

相關連結

  

此文章由 will 發表於 2009/8/31 下午 04:48:53

永久連結 | 評論 (1) | 此文章的RSSRSS comment feed |

分類: ASP.NET | Oracle | Visual Studio

標籤: , , ,

收藏:

解決 SQL Server 資料庫無法啟用 Service Broker 的問題

我們今天有個案子遇到一個很緊張的狀況,因為正式機的 SQL Server 資料庫沒人管一段時間了 (因為網站還沒正式對外上線),結果資料庫的交易記錄竟然把硬碟給塞爆了,這導致資料庫再也無法寫入資料而網站也自然無法使用,我們得知狀況後立即告知負責管理資料庫的 DBA 處理狀況。

由於透過 T-SQL 清除交易記錄失敗 (也許是硬碟已滿的關係),他就試著直接將 *.ldf 交易記錄檔直接刪除,再將 *.mdf 掛回資料庫,但掛回去之後卻讓我們原本運作的 Service Broker 失效了。

這時用我常用的 T-SQL 語法卻無法啟用資料庫的 Service Broker 功能,發生的錯誤訊息如下:

無法在資料庫 "<DBName>" 中啟用 Service Broker,因為資料庫 (<GUID>) 中的 Service Broker GUID 與 sys.databases (<GUID>) 中的不相符。

英文的錯誤訊息是:

Cannot enable the Service Broker in database "<DBName>" because the Service Broker GUID in the database (<GUID>) does not match the one in sys.databases (<GUID>).

以下是我經常用來啟用 Service Broker 的 T-SQL 語法 ( ENABLE_BROKER ):

USE [master]
GO
ALTER DATABASE [YourDBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE [YourDBName] SET SINGLE_USER
GO
ALTER DATABASE [YourDBName] SET ENABLE_BROKER
GO
ALTER DATABASE [YourDBName] SET MULTI_USER
GO

但由於 GUID 不一致,原本的 Service Broker 已經無法使用了,這時必須設定一組新的 Service Broker 才行,所以必須修改成以下 T-SQL 語法 ( NEW_BROKER ):

USE [master]
GO
ALTER DATABASE [YourDBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE [YourDBName] SET SINGLE_USER
GO
ALTER DATABASE [YourDBName] SET NEW_BROKER
GO
ALTER DATABASE [YourDBName] SET MULTI_USER
GO

問題就迎刃而解。

相關連結

  

此文章由 will 發表於 2009/8/29 上午 12:13:50

永久連結 | 評論 (0) | 此文章的RSSRSS comment feed |

分類: SQL Server

標籤: , ,

收藏:

機會教育:從中華民國總統府網站被發現 XSS 漏洞講起

昨晚從黑暗執行緒那邊得知中華民國總統府網站已經淪陷了,看到總統府新聞稿一直在跳 Sorry Sorry 舞蹈,雖然只是網友惡搞,但估計這個 Cross-Site Script (XSS) 弱點可能會遭受駭客利用,騙那些好奇的鄉民點選觀看,也許背地裡會潛藏木馬或病毒在其中,各位千萬要小心啊!

總統府網站新聞稿的頁面使用了非常糟糕的設計法,導致可以讓頁面插入任意標籤(Tag Injection),雖然無法直接插入 <script> 標籤,但是至少可以插入 IFRAME 嵌入任意網頁,而且 IFRAME 只要加上 onload 屬性就等於可以執行 JavaScript 了,危險程度「極高」!

此網站可能引發的潛在危機包括:

我個人認為這已經是一個高危險性的網站了,我的 IE8 雖然有內建防止 XSS 攻擊的保護功能,但我還是將該網站網址加入「網際網路選項」的「限制的網站」,以確保不會遭受攻擊,設定方式如下圖:

「網際網路選項」的「限制的網站」

除此之外,我以 2007 年 OWASP 公佈的 Web 十大弱點, 分析總統府網站還有以下問題存在:

OWASP Top 10 在總統府就包辦 6 項,這真是一場給 Web 開發人員絕佳的機會教育阿!

依我個人的經驗判斷,該總統府網站可能有以下特點:

  • 採用 PHP 程式語言,版本竟然是 4.3.2 版,實在太舊太舊了!
    • 這種古董級的 PHP 漏洞少說也上百個,而且版本號還沒隱藏,這簡直是駭客的春藥。
    • 這也代表該網站已經年久失修了,應該是多年前完成的案子,搞不好連維護廠商都沒了。
    • 從網址列判斷這裡的 PHP 應該是以 CGI 的方式運作,非常吃系統資源,要是被 DoS 一下網站應該就會關了。
  • 採用 AIX 或 Linux 或 FreeBSD 或 Solaris 平台
    • 以 PHP 的版本研判,OS 版本也不會多新才對。
  • 採用 Apache 網站伺服器 ( 版本號已被隱藏,這點值得鼓勵 )
    • 以 PHP 的版本研判,Apache 版本也不會多新才對。
  • 採用 MySQL 資料庫,目前好像只有 MySQL 有 limit 語法,從錯誤訊息就看的出來
    • 以 PHP 的版本研判,MySQL 版本也不會多新才對。

我個人寫 PHP 的經驗約有 9 年,我知道 PHP 很容易上手,開發網站也很快,但就是缺乏工具與架構,雖然目前市面上已經有不少工具與架構可選擇,但舊有的網站還是很多,很難一口氣修正所有的缺點,相對的網站弱點也是非常多,這是個難解的問題,需要時間與金錢才能徹底解決。

最後,我有以下建議:

廣大使用者

  • 不要好奇點選任何來路不明的連結
  • 不要開啟任何來路不明的郵件或附件

所有Web開發人員

  • 要將撰寫安全的程式(Write Secure Code)的技能練到跟呼吸一樣自然,安全的程式永遠比高效能的程式來的重要,千萬不能本末倒置。
  • 多吸收些安全相關的知識,瞭解攻擊方法預防被攻擊一樣重要,一把刀兩面刃,不要做壞事就對了。

PHP 開發人員

  • 以我的個人經驗,修正弱點很容易也很快,難的是「知道弱點在哪裡」!
  • PHP 真的很容易寫出有漏洞的程式,我很難給你們建議,連我自己寫的 PHP 程式都被攻陷過,我個人認為需要「原始碼檢測軟體」才能較快的找到弱點所在,並且一口氣修復所有安全弱點。
  • 近期我們公司應該會提供這類的顧問服務,有需要這類檢測服務的人可以跟我聯絡。

總統府網站相關人員

  • 第一步:先關閉網站
  • 第二步:修正網站「已知」的弱點後再開站  [ 備註: 今天早上總統府網站已經緊急修復該弱點了 ]
  • 第三步:修正網站「未知」的弱點,透過「原始碼檢測軟體」找出所有弱點並一次修復
    • 對知名網站來說,這是最經濟實惠的策略!
    • 我相信總統府的網站一定有防火牆設備,但請不要花大錢再買更高階的防火牆了,程式碼安全更重要。
  • 第四步:找到對的廠商將網站改版
    • 總統府網站應該不複雜,重新製作一遍不用幾個月就完成了。
    • 改版不代表「安全」,先有安全的常識與觀念才會有安全的網站。
    • 建議汰換現有的所有軟硬體,連作業系統也要升級

總統府網站的建置廠商或系統管理者

  • 隱藏所有軟體版本資訊 ( Linux, Apahce, MySQL, PHP, … )
  • 隨時更新作業系統、網站伺服器、資料庫伺服器、PHP 的版本,任何已知的patch都需要定時更新
  • 不要信任所有從 Browser 端傳來的資料,對所有網路輸入的參數進行檢核 ( QueryString, POST Data, Cookies, All HTTP Headers )
  • 對所有輸出到網頁的資料進行 HTML Encode 或 URL Encode
  • 隱藏所有可能會揭露網站技術細節的資訊
  • 將前、後台區分兩個不同的網域(Domain) => 不是 Active Directory 那種網域喔!

這篇文章原本昨天晚上就寫好了,想說等等看今天早上問題會不會修復,不然若文章發出去可能就有一堆人想 try 總統府網站,那我就是罪人了。

還好總統府網站今天一早睡醒就已經修復完畢,雖然目前已經看不到原本的弱點頁面會再跳出訊息,且從弱點被發現到解決的時間雖然不到 12 小時,但漏洞存在的時間確實有很長一段時間,況且還有哪些弱點目前還不知道,不過依照目前的程式寫法來說,弱點一定還會有,所以還是小心一點為妙。

  

此文章由 will 發表於 2009/8/28 上午 09:17:00

永久連結 | 評論 (14) | 此文章的RSSRSS comment feed |

分類: Web | PHP | Security

標籤: , , ,

收藏:

物件導向基礎:何謂類別(Class)?何謂物件(Object)?

每次有新人來面試,我都會問新人這個很基礎的程式開發問題,想聽看看來面試的人如何解釋這個每天朝夕相處的東西,但很難想像的是竟然有大部分的面試者都無法回答出讓我滿意的答案,不是支支吾吾的講不清楚,就是只能講出他們語法上的差別(錯誤觀念),但卻無法清楚且具體的描述何謂類別、何謂物件。

以下是一些我之前在面試人員時聽到的解釋法:

含糊帶過

  • 類別:就是 class 啊~  ( 這…我不是請你來翻譯的 )
  • 物件:物件不就是可以 new 的那種嗎?  ( 對,但這樣回答不太好吧… )

簡單帶過

  • 類別:定義程式的方法、屬性
  • 物件:可執行的東西

裝死

  • 類別:我不知道 ( 可能是沒自信說出來或真的不知道? )   <= 最糟糕的答案!
  • 物件:我不知道 ( 可能是沒自信說出來或真的不知道? )   <= 最糟糕的答案!

我知道程式設計的領域有許多抽象概念,很多東西無法清楚的「直接」描述,所以要瞭解抽象概念就需要透過「比喻」來描述才比較能讓人瞭解,所以我建議那些講不出抽象概念的人要多學著用「比喻」的方式講解抽象概念,你能將抽象概念描述的越具體,相對的你對技術的掌握也越精準。

我個人所學到大部分的程式技能都是透過自修而來的,過程中經常沒人帶領,甚至找不到人可問,除了靠自身的興趣與熱情外,還需要靠大量的時間去消化、去理解、去求證,過程可說十分痛苦,但熱情如同嗎啡一般,確實可以減低許多自我成長時的痛苦感。

程式菜鳥在學習抽象概念時經常一知半解,若自己不求甚解的話久而久之真的會變成半弔子,變成只會寫 Code 的人(Coder),而不是 Programming 的人(Programmer),不但未來的路途變窄了,寫程式也會缺乏很多創意,沒有創意也就沒有熱情了。

首先聲明

  • 我不是什麼學者,講不出課本要的正確答案,想知道正確答案請查閱物件導向相關書籍。
  • 如果你問 100 個人這個問題,可能會得到 200 個答案,所以你一定要有自己獨到、有自信、精闢的見解或描述方式。

★ 我的個人見解:

類別(Class) 物件(Object) 是個一體兩面的東西,以下我用幾個不同的方式說明這兩著的差別:

簡單解釋:

  • 類別算是一個藍圖、一個範本、一個可參考的文件,他沒有 實體 (Instance),屬靜態的。
  • 物件是一個看的到、摸的到的實體,屬於動態的,狀態會隨時改變,但架構與行為不會改變。

比喻一:建築物

  • 類別:設計藍圖
  • 物件:實際蓋好的房子
  • 兩者關係:設計藍圖(類別)決定房子應該怎麼蓋,決定幾台電梯、幾間房間、走道如何設計。實際蓋好的房子(物件)是照著設計藍圖所蓋出來的房子,人只能照設計藍圖的設計使用這間房子。

比喻二:蓋世武功

  • 類別:武林密笈
  • 物件:修練武林密笈而成的武林高手
  • 兩者關係:武林密笈(類別)記載許多各種攻擊與回應的方式,讓武林高手(物件)知道遭遇到什麼攻擊時要用什麼招式回應。
  • 程式設計:每執行到我們用 new 運算子時,等同於將物件產生,也等同於成功得到武林密笈可以開始練功,或是在「建構子」的時候就已經賦予你基本功力。

基本上,類別只用來決定物件形成時的樣子,當物件形成時,物件就變成一個記憶體中的空間,記載著物件活動時暫存的資料與狀態,並且當有類別存在時有能力透過方法(Method)執行一些動作。

以下幾個基本的考題考考各位,看有沒有人可以回答出正確答案:

  1. 請問「類別」可不可以包含「物件」?
  2. 請問「物件」可不可以包含「類別」?
  3. 請問「類別」可不可以包含「類別」?
  4. 請問「物件」可不可以包含「物件」?
  5. 請問「物件」可不可以當成資料傳遞?
  6. 請問「類別」可不可以當成資料傳遞?
  7. 在 .NET 的世界,請問「物件」可以用什麼型態存在或用什麼格式傳遞?(可任意回答一種以上)
  8. 在 .NET 的世界,請問「類別」可以用什麼型態存在或用什麼格式傳遞?(可任意回答一種以上)
  9. 在 .NET 的世界,程式在執行的時候,「類別」可不可以被動態修改?
  10. 如果有兩台主機要互相傳遞資料,他們傳遞的是「類別」還是「物件」?
  11. 請問「物件」是否包含「方法(Method)」?
  12. 如果「物件」從 A 電腦傳遞到 B 電腦時,若該物件要執行「方法」還需不需要有「類別」存在?

這些問題每個人看的時候理解可能不同,甚至於可能覺得題目有問題(模稜兩可或題目不合邏輯或錯誤),若覺得題目有問題在回答時需明確說明哪裡有問題。所以每個人的答案也許也很不一樣,你們就用自己的理解來回答即可,不用害怕答錯。

2009/10/1 更新

解答請見:物件導向基礎:何謂類別(Class)?何謂物件(Object)? [解答]
看解答前建議先回答問題,物件的問題一定要自己動腦思考,否則學習效益不大。

  

此文章由 will 發表於 2009/8/27 下午 09:23:11

永久連結 | 評論 (9) | 此文章的RSSRSS comment feed |

分類: .Net | 心得分享

標籤: , , ,

收藏:

Windows 7 如何新增TCP/IP網路印表機及自動下載驅動程式

像我公司有導入 AD 網域,所以電腦全部都有加入網域,但是我們的「網路印表機分享器」卻無法加入網域,以前在使用 Windows XP 或 Windows Vista 都可以直接以 UNC 路徑直接加入那台網路印表機,但到了 Windows 7 不知為何就是無法新增成功,以下是我最後新增成功的過程筆記。

點選 [開始] 並輸入 printer 搜尋,再選取 [Add a printer] 或 [新增印表機]

點選 [開始] 並輸入 printer 搜尋,再選取 [Add a printer] 或 [新增印表機]

選取 [Add a network, wireless or Bluetooth printer]

選取 [Add a network, wireless or Bluetooth printer]

我就是在選擇印表機的時候會失敗

我就是在選擇印表機的時候會失敗,這時必須要選取 [The printer that I want isn’t listed] 進行安裝

選取失敗時會出現以下錯誤,這時必須要選取 [The printer that I want isn’t listed] 進行安裝

選取失敗時會出現以下錯誤: Connect to Printer

選取 [Add a printer using a TCP/IP address or hostname]

選取 [Add a printer using a TCP/IP address or hostname]

這時要選取印表機驅動程式,但這時可能會找不到我們要的印表機型號,必須點選 [Windows Update] 進行下載

這時要選取印表機驅動程式,但這時可能會找不到我們要的印表機型號,必須點選 [Windows Update] 進行下載

此時大約會花個 5 – 10 分鐘進行檔案下載,時間有點長,可能要耐心等候

此時大約會花個 5 – 10 分鐘進行檔案下載,時間有點長,可能要耐心等候

這時電腦會多出非常多微軟幫我們準備好的驅動程式,應該大多驅動程式都能找到才對

這時電腦會多出非常多微軟幫我們準備好的驅動程式,應該大多驅動程式都能找到才對

接著輸入印表機的名稱後進行安裝

接著輸入印表機的名稱

image

最後會問你要不要分享印表機給別人用

最後會問你要不要分享印表機給別人用

如果你要列印測試頁可以點選 [Print a test page]

如果你要列印測試頁可以點選 [Print a test page]

大功告成。

  

此文章由 will 發表於 2009/8/26 下午 10:27:12

永久連結 | 評論 (0) | 此文章的RSSRSS comment feed |

分類: 系統管理

標籤: , ,

收藏: