Tuesday, November 10, 2009 - 文章

【茶包射手專欄】aspnet_regiis加密失敗的還原

同事遇到狀況,用aspnet_regiis加密web.config的ConnectionString區段,過程發生錯誤(錯誤訊息不可考),之後ASP.NET程式不管點選任何ASPX連結都呈現無法顯示(Hang住遲無回應)。

我找到Global.asax裡有段Application_OnStart涉及資料庫存取,懷疑它是導致所有ASPX都癱瘓的源頭。先跳過其中的邏輯,就進入下一關,得到以下訊息:

無法使用提供者 'RsaProtectedConfigurationProvider' 解密。來自這個提供者的錯誤訊息為: 無法開啟 RSA 金鑰容器。
Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.

猜想這與先前加密設定過程出錯有關,我的計劃是先退回到原本設定前的狀態再做打算。決定砍掉重練---用aspnet_regiis -u / aspnet_regiis -i 重新註冊ASP.NET,或許可以洗掉不好的記憶(與開大水沖澡有異曲同工之妙)。

不幸地,解除並重新註冊ASP.NET並沒能解決問題。再追了一下,發現\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config的檔案時間是今天寫入的,意思是aspnet_regiis -i時並不會還原它到預設狀態。此時,我發現同一目錄下有個web.config.default,檔案大小與內容與web.config相近,八成是微軟留下來的還原用滴,那我就不客氣了,用web.config.default覆寫web.config,問題排除,收隊回家!

TOOLS-IDbCommand.Parameters抓漏工具

不知天生粗枝大葉還是怎樣,每回只要操作大量欄位Table的新增修改,我總會迷失在茫茫的Parameter大海中...(這也解釋了為什麼我愛死了LINQ to SQL/LINQ to Oracle)

複雜的資料表有三四十個欄位是家常便飯,CommandText就得宣告三四十個參數名稱,然後照著這堆參數名稱一一Parameters.Add,只要名稱打錯或多一個少一個,就會冒出"ORA-01036 illegal variable name/number 變數名稱/號碼無效"之類的錯誤,通知我練眼力的時間到了! 此時別無他法,只能逐一檢查有無打錯字,多參數少參數的。動轍要核對三四十個參數名稱,對耐性欠佳的我是種折磨,偶爾甚至會有輕生的念頭...

為了避免自己常陷入性命攸關的危機,我寫了一個工具函數來幫忙檢核。如以下的範例,一旦Parameter數目、名稱與CommandText中的宣告對不上,就會得到警告:

System.Data.OracleClient.OracleCommand cmd = 
    new System.Data.OracleClient.OracleCommand();
cmd.CommandText = "insert into pack values (:v_id, :v_name, :v_count)";
cmd.Parameters.Add("v_name", OracleType.VarChar).Value = "Item1";
cmd.Parameters.Add("v_id", OracleType.Number).Value = 1;
//cmd.Parameters.Add("v_count", OracleType.Number).Value = 100;
cmd.Parameters.Add("v_wtf", OracleType.VarChar).Value = "WTF";
string result = DbJobHelper.VerifyCommandParameters(cmd, ":v_", false);
Response.Write(result);

結果為: Parameter[v_wtf]-not used! Parameter[:v_count]-missing!

另外,函數還提供了reorder的功能,讓Parameter可以依其在CommandText裡的出場順序重新排列。

程式碼如下,需要的朋友請自取:

    /// <summary>
    /// IDbCommand.Parameters檢核,找出Parameters數目不合問題
    /// </summary>
    /// <param name="cmd">IDbCommand物件</param>
    /// <param name="prefix">CommandText中的參數名特徵,如:v_, @p_</param>
    /// <param name="reorder">是否重新依參數出場順序排序</param>
    /// <returns></returns>
    public static string VerifyCommandParameters(
        IDbCommand cmd, string prefix, bool reorder)
    {
        Dictionary<string, string> paramSymbolCheck = 
            new Dictionary<string, string>();
        Dictionary<string, string> paramUsageCheck = 
            new Dictionary<string, string>();
        Dictionary<string, IDataParameter> paramPool = 
            new Dictionary<string, IDataParameter>();
        List<string> paramOrder = new List<string>();
        string s = "";
        for (int i = 0; i < prefix.Length; i++)
            s += "[" + prefix.Substring(i, 1) + "]";
        //用RegEx找出CommandText中的參數宣告
        foreach (Match m in Regex.Matches(cmd.CommandText,
            "(?ims)(?<n>" + s + "[a-zA-Z0-9_]+)"))
        {
            //OracleParameter要去掉前方的:才是ParameterName
            string pn = m.Value.ToUpper().TrimStart(':');
            paramSymbolCheck.Add(pn, m.Value);
            paramOrder.Add(pn);
        }
        //找出所有參數物件
        foreach (IDataParameter p in cmd.Parameters)
        {
            paramUsageCheck.Add(p.ParameterName.ToUpper(), 
                p.ParameterName);
            paramPool.Add(p.ParameterName.ToUpper(), p);
        }
        StringBuilder sb = new StringBuilder();
        //檢查是否每個Parameter都有被用到?
        foreach (string n in paramUsageCheck.Keys)
        {
            if (!paramSymbolCheck.ContainsKey(n))
                sb.AppendFormat("Parameter[{0}]-not used!\n", 
                    paramUsageCheck[n]);
        }
        //檢查是否每個參數宣告都有對應的Parameter?
        foreach (string n in paramSymbolCheck.Keys)
        {
            if (!paramUsageCheck.ContainsKey(n))
                sb.AppendFormat("Parameter[{0}]-missing!\n", 
                    paramSymbolCheck[n]);
        }
        //依出現順序重排參數
        if (sb.Length == 0 && reorder)
        {
            cmd.Parameters.Clear();
            foreach (string n in paramOrder)
                cmd.Parameters.Add(paramPool[n]);
        }
        return sb.ToString();
    }

搜尋

Go

<November 2009>
SunMonTueWedThuFriSat
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication