星期二, 7月 23, 2013

政府測試憑證的問題

從今年三月起,由於保證等級的問題,測試憑證管理中心必須獨立出來。但直到最近,發出來的測試憑證關於「發行單位」的憑證連結,仍然是指向舊的。寫信去反映,倒是很快(半天)得到答案:請自行下載。意思是不理我就對了。
錯的事情不改正,這就是我們的政府,或懷有國營事業心態的承商。也對啦,這又不是什麼大事,軍中都能整死人了,沒有體制只靠人治豈不多見?

Mac 常失眠

自從改用 Mail 收信,我的 MacBook 就常失眠,每次蓋上螢幕拔電拔網路下班,到家就一付熱到快爆炸的樣子。原來是因為電源管理預設插座供電時,即使休眠也要繼續收信,難道蘋果認為大家都已經有吃到飽的網路了?找解法的過程並不順利,一度曾以為可以了,過幾天又出狀況。經過約一個月的驗證,最後的做法是增加一個「沒有網路」的網路組態,每次下班前都是調到這再蓋螢幕拔電拔網路,應該是確定可以了。

星期四, 7月 18, 2013

Visual Studio 2013 Preview Bug?

有兩個都是 .NET 2.0 的專案,專案一依賴專案二,專案二建置沒問題,但專案一在 Visual Studio 2013 Preview 始終無法建置,非得升到 .NET 4.0 不可,而這情形在以前的 Visual Studio 2012 並不存在。
比較值得懷疑的,是專案二有參考到 COM 元件,不知道那個 Interop 介面(也重新產生過)是不是綁到 .NET 4.0 去了?用 ildasm.exe 一看,果然沒錯。歸根究底,與開發工具自動產生的 Interop 介面有關,VS2012 用 .NET 2.0 的 Tlbimp.exe,而 VS2013 用 .NET 4.0 的 Tlbimp.exe。知道原因後,想解決這個問題就簡單了,自已在命令列用適當的工具產生即可,例如:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\Tlbimp xxx.dll -> 2.0
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\Tlbimp xxx.dll -> 4.0

星期三, 7月 17, 2013

cabarc.exe 藏身之地

原本有一個專屬的 Cabinet SDK,但很久以前就找不到微軟官網下載點了,所以一直用別家網站留的,不是很放心。如果是比較單純的狀況,MakeCab.exe 也許勉強能用,在系統目錄就已內建。今天發現在 IEAK 10 竟然有含,相信 IEAK 9、IEAK 8 也是吧?下次有空再驗證。

安裝玉山銀行 WebATM 之後的 Mac 無法在 VM Guest 用讀卡機

玉山銀行的 WebATM 首先能在 Mac 使用晶片讀卡機,做得漂亮!可惜一但安裝,虛擬機器的讀卡機就會因「忙碌」而連不上,即便是關閉瀏覽器甚至重開機都無效。
究其原因,有一個「pcscd」持續地佔住讀卡機,即使原先不在,只要一插上就歸它管,而且這個程序殺了一秒鐘又會再起來,所以想「暫停」得費點工夫:
  • ps -ef | grep pcscd | grep -v grep | awk '{print $8 "\t" $2}' -> 取得 path 與 processId
  • sudo chmod -x path
  • sudo kill processId
當虛擬機器不再使用,想要恢復 WebATM 時:
  • sudo chmod +x path
[2013/08/13 補充]
後來發現兩個缺點:一是因為找不到原來的 path 而無法恢復,二是在 Consloe 會有很多錯誤訊息,所以那只是個治標不治本的爛方法呀!依據錯誤訊息為線索,在我的機器上可以找到 /Library/LaunchDaemons/org.opensc.pcscd.plist 以及 /Library/LaunchDaemons/org.opensc.pcscd.autostart 兩個內容一模一樣的檔案,而且那個找不回來的 path 都出現了。所以想「暫停」的步驟可改成:
  • sudo launchctl unload /Library/LaunchDaemons/org.opensc.pcscd.plist
  • (可省略)sudo rm /Library/LaunchDaemons/org.opensc.pcscd.plist
恢復:
  • (可省略)sudo cp /Library/LaunchDaemons/org.opensc.pcscd.autostart /Library/LaunchDaemons/org.opensc.pcscd.plist
  • sudo launchctl load /Library/LaunchDaemons/org.opensc.pcscd.plist
  • (如果前一次用的是舊方法暫停,再加上)sudo chmod +x path
[2015/08/24 補充]
Yosemite 已不再使用 pcscd,所以招術失靈,請參考這篇

星期一, 7月 15, 2013

信任一個懶惰又小氣的安全網站

要從標題這句話倒過來解釋:
  • 安全網站:傳輸過程經 SSL 安全通道加密。
  • 小氣:或者可以說「節儉」,不願交保護費給 Verisign 這類大公司。自簽根憑證,再據以發行網站憑證。
  • 懶惰:不積極宣導如何信任我的網站,也沒有提供散佈憑證的安全管道。
  • 信任:安裝對方的自簽根憑證。
首先要取得對方的自簽根憑證:在 Windows 作業系統,最簡單的方式是用 Firefox,到了這種網站之後選「我了解此安全風險」、「新增例外網站」、「取得憑證」、「檢視」、「詳細資訊」、「(最上一個)憑證層級」、「匯出」、「儲存」到一個臨時檔案。
接下來是安裝:此時可以關閉 Firefox,然後在該檔點兩下,「安裝憑證」到「使用者」或「電腦」的「受信任」,或「電腦」的「第三方」根憑證存放區,如此一來不論是透過 IE 或 Chrome 都已信任這個安全網站。至於 Firefox 請到「選項」、「進階」、「檢視憑證清單」、「憑證機構」、「匯入」上述的臨時檔案。

[2014/06/05]

到了最近比較新的作業系統,例如 Windows 8.1,可能要改放到「受信任的人」憑證存放區。

星期四, 7月 11, 2013

不是 Cross-origin resource sharing 難,而是⋯⋯

整理幾個最近遭遇的問題:
  1. Microsoft IE 11.0.9431.0 在 localhost 但 port 不同的情況下,認為這不算跨域,沒作預檢(preflight),直接發送真正需要的 Request。
  2. Google Chrome 28.0.1500.71 即使預檢失敗,仍會發送真正需要的 Request。
  3. Microsoft IIS 8 即使未設 Access-Control-Allow-Methods,仍接受 GET、OPTIONS。
  4. System.Web.Http.ApiController 的子類別最好多寫一個空的方法「public void Options() { }」,否則 Firefox 預檢失敗,就不發送真正需要的 Request 了,雖然這是最標準的,但讓我誤會了好幾個小時,以為怎麼 IE 10、Chrome 都正常,唯獨 Firefox 不行?

星期三, 7月 10, 2013

從瀏覽器呼叫 Restful Web API 的要訣

前文所提,瀏覽器要支援 Cross-origin resource sharing,Firefox 或 Chrome 都沒問題,IE 只有 10 或更新的版本才有機會,而且要看文件模式(Document Mode)是不是「標準」或「相容」(Quirks),若其他像是 Internet Explorer 9 standards、Internet Explorer 8 standards 等都不行。
問題來了,若使用者雖然是 IE 10,但他調成不支援的文件模式,要如何交待?這時必須先用 JavaScript 偵測,並在不符條件的情況下提示。但用 navigator.userAgent 是無效的,因為它只對瀏覽模式(Browser Mode)有反應,對文件模式一無所知。幸好 IE 還有個特別的屬性叫 document.documentMode,如果小於 10 再提示就對了。
網路上也有人提到,即使是 IE 8 或 IE 9,還是有機會支援,只是限制一大堆。但連 jQuery 都明確表態不會採納了,我這種小角色又何必為難自己?

星期二, 7月 09, 2013

英國鍵盤不等於英文鍵盤

我的 Windows 8 是「英國英文版」,不知是否當初買錯了?相對於熟悉的「美式國際鍵盤」排列,「@」和「"」的位置是對調的,更糟的是「#」變成英鎊符號。

星期五, 7月 05, 2013

JSONP 的真相

現在很流行用 Ajax 到伺服端要物件回瀏覽器呈現,物件怎麼從 HTTP 上走下來?靠的就是 JSON。那 JSONP 呢?原本僅以 JSON 回傳物件,多加的 P 是指 Padding,填補成「對回呼函式的呼叫」,而 JSON 改用來封裝呼叫函式時的引數。

Restful Web API 服務與測試分離

過去我的 Restful Web API 在跨域限制下為了方便,都把服務本身與測試服務的網頁放在同一個網站,但這讓人蠻不舒服的。想要把它們分開,網路上大致流傳著兩種解法:JSONP 與 Cross-origin resource sharing,研究之後發現,前者其實改變了服務的介面,不敢領教,所以決定用後者。有幾個要點(假設服務在 http://localhost/myService,測試首頁在 http://localhost:12345/test.html):
  • 服務端要設定對測試來源開放,以 IIS 7 為例,在 Web.config configuration -> system.webServer -> httpProtocol -> customHeaders 需要以下的節點:<add name="Access-Control-Allow-Origin" value="http://localhost:12345" />
  • 測試端我用的是 jQuery 發送 Ajax,它當然也要知道服務在哪提供,像這樣:$.ajax({url: "http://localhost/myService", success: ..., error: ...});
  • 測試端使用的瀏覽器會挑,像 IE 10 以前都不行,但 Firefox、Chrome 就沒這問題,可能要注意一下。
  • 若在 Visual Studio 同一 Solution,StartUp Project 設在測試專案,Start Page 設在測試首頁,服務專案的 Properties -> Web -> Start Actions 設在「Don't open a page. Wait for a request from an external application.」,這樣才會同時載入兩個網站。

星期四, 7月 04, 2013

在 ASP.NET 做簡單的 Ajax + JSON 測試

  1. Visual Studio 新建方案,範本挑 ASP.NET Empty Web Application 就可以了,其他較複雜的應該更沒問題。
  2. .NET Framework 版本沒特別要求,現在的 2.0 到 4.5 都可以。
  3. Web.config 沒什麼要加要改的。
  4. 這次實驗用的是 jquery-1.8.2.min.js,但版本應該沒什麼限制。
  5. 新建測試首頁,名為 Test.html
    • <script type="text/javascript" src="jquery-1.8.2.min.js"></script>
    • function query() {
          $.ajax({
              url: "/Test.ashx",
              success: function (time) {
                  $("#timeCell").text(time.now);
              }
          });
      }
    • <input type="button" onclick="query()" value="query" />
    • <td id="timeCell"></td>
  6. 新建 Generic Handler,名為 Test.ashx
    • using System;
    • using System.Web;
    • public void ProcessRequest(HttpContext context)
      {
          context.Response.ContentType = "text/json";
          context.Response.Write("{\"now\": \"" + DateTime.Now + "\"}");
      }

簡易 Workflow

在 Java 的世界有 Activiti,微軟的 Workflow Fundation 硬是輸人一大截,連拉個流程都要先寫一個 WPF 程式,還好照 MSDN 抄來再改就可以了。剛開始一時看不懂,怎麼範例文件上人家有的我都沒有?原來是要裝 Visual Studio Express for Desktop 才行,for Web 幫不上忙的。

IIS Express 開放非本機電腦連入

IIS Express 預設是只讓本機的瀏覽器連入,但有時這不夠,例如要從虛擬機器進來,或是代理伺服器的限制等。其實很容易改,只要找 IISExpress\config\applicationhost.config 檔案中相關的站台設定,類似以下片段(假設是 http://localhost:54321):
<configuration>
    <system.applicationHost>
        <sites>
            <site>
                <application>...</application>
                <bindings>
                    <binding protocol="http" bindingInformation="*:54321:localhost" />
                </bindings>
            </site>
        </sites>
    </system.applicationHost>
</configuration>
只要將 localhost 刪除就好了,該行變成像這樣:
...
<binding protocol="http" bindingInformation="*:54321:" />
...
記得存檔後重啟 IIS Express,而且因為開放的對象變大,權限也要隨之提高。像我都是利用 Visual Studio Express 啟動,要記得開發工具本身也必須「以系統管理員身分執行」。
有時也會遇到所謂「非本機」其實還是本機,但就是不能從 http://localhosthttp://127.0.0.1 來,非要走 http://computername 這條路,但本機的網路怎知 computername 就是我?這種情況下就去編輯 C:\Windows\System32\drivers\etc\hosts 吧。