<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>ASP.NET權限控管</title><link>http://blog.blueshop.com.tw/topcat/category/2554.aspx</link><description>ASP.NET權限控管</description><managingEditor>topcat</managingEditor><dc:language>zh-TW</dc:language><generator>.Text Version 0.95.2004.101</generator><item><dc:creator>topcat</dc:creator><title>ASP.NET進階權限控管-Part 3 角色管理與角色使用者維護</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55209.aspx</link><pubDate>Mon, 09 Jun 2008 17:16:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55209.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/55209.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55209.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/55209.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/55209.aspx</trackback:ping><description>&lt;h1&gt;緣起&lt;/h1&gt;&lt;p&gt;承繼前兩篇，從第一篇的【&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/05/07/3826.aspx"&gt;願景&lt;/a&gt;】，與第二篇的【&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/05/09/3914.aspx"&gt;樹狀結構畫面維護&lt;/a&gt;】，這一篇來談談如何處理角色的部分。角色的意義，請參考小喵第一篇【&lt;a href="http://www.dotblogs.com.tw/topcat/archive/2008/05/07/3826.aspx"&gt;ASP.NET進階權限控管-Part 1 願景&lt;/a&gt;】裡面的說明，這裡就不再贅述了。直接進入到角色的定義、以及角色&amp;larr;&amp;rarr;使用者之間的關係如何維護。&lt;/p&gt;&lt;p&gt;先從角色的定義來談起，先看一下角色的欄位說明&lt;/p&gt;&lt;p&gt;Role&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole001_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="188" alt="PRole001" width="626" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole001_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;RoleUser&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole002_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="188" alt="PRole002" width="625" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole002_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1&gt;維護畫面設計&lt;/h1&gt;&lt;h2&gt;角色維護&lt;/h2&gt;&lt;p&gt;再來是設計角色的維護畫面、以及角色&amp;larr;&amp;rarr;使用者的維護畫面。角色維護畫面其實還蠻簡單的，一個GridView配合一個DetailView就完成了，這部分的程式碼就不再浪費版面。類似以下的畫面，在撰寫的時候要注意，&lt;font color="#ff0000"&gt;&lt;strong&gt;一旦修改或者刪除角色，必須同步的去修改刪除相關的資料表RoleUse(角色使用者設定),MenuP(畫面權限設定)&lt;/strong&gt;&lt;/font&gt;。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole003_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="109" alt="PRole003" width="568" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole003_thumb.jpg" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;而角色使用者的維護，這個部分比較有趣了。因為一個人可能擔任數個角色；同樣的，一個角色可能有多人擔任。因此會有兩個方向的維護：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;使用者&amp;rarr;角色&lt;/li&gt;&lt;li&gt;角色&amp;rarr;使用者&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;使用者&amp;rarr;角色&lt;/h2&gt;&lt;p&gt;小喵把使用者&amp;rarr;角色的部分，跟使用者維護放在一起，這樣操作起來比較直觀，就是設定某個人的個人資料，並且設定該人擔任哪些角色，請看畫面如下：&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole004_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="232" alt="PRole004" width="244" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole004_thumb.jpg" /&gt;&lt;/a&gt; &lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole005_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="221" alt="PRole005" width="244" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole005_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;這個部分程式上也沒有太大的困難，在使用者設定歸屬角色時，會用到一個技巧【&lt;a href="http://www.dotblogs.com.tw/topcat/archive/2008/03/05/1243.aspx"&gt;物件導向的購物車(動態新增移除輸入資料) &lt;/a&gt;】不同的是不需要使用Session來記錄，可以改以ViewState處理即可。使用ViewState記錄物件，必須要序列化，這也只需要在設定物件的時候，多宣告成可序列化即可。這裡物件宣告的部分，小喵把他列在下面&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;textarea class="vb" name="code"&gt;&amp;lt;Serializable()&amp;gt; Public Class UserRole
    Dim mRoleId As String
    Dim mRoleDesc As String

    Public Property RoleId() As String
        Get
            Return mRoleId
        End Get
        Set(ByVal value As String)
            mRoleId = value
        End Set
    End Property

    Public Property RoleDesc() As String
        Get
            Return mRoleDesc
        End Get
        Set(ByVal value As String)
            mRoleDesc = value
        End Set
    End Property


End Class
&lt;/textarea&gt;&lt;/p&gt;&lt;p&gt;以上的Class不必獨立撰寫，直接寫再使用者維護的aspx.vb裡面即可(一個檔案可以有數個Class)&lt;/p&gt;&lt;h2&gt;角色&amp;rarr;使用者&lt;/h2&gt;&lt;p&gt;接著設計另一個方向：角色&amp;rarr;使用者。也就是某個角色，設定哪些使用者擔任這個角色。先看一下畫面如下&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole006_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="PRole006" width="244" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=PRole006_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;這部分的設計，方法是衍生自物件導向式資料庫的方式，在畫面上用兩個物件及兩個物件集合即可做到。相關方法請參考小喵在小舖裡發表的一篇文章【&lt;a target="_blank" href="http://www.blueshop.com.tw/download/show.asp?pgmcde=PGM20060725095226DOM"&gt;ASP.NET 左右ListBox項目動態轉移範例&lt;/a&gt;】。一樣的並不需要用到Session，只要用ViewState即可。使用ViewState記得要把物件宣告成可序列化。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;有了使用者、角色、畫面之後，接著下一篇將開始介紹如何設定授權。敬請期待&lt;/p&gt;&lt;p&gt;^_^&lt;/p&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/55209.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>ASP.NET進階權限控管-Part 2 登入結合資料庫、樹狀結構維護</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55208.aspx</link><pubDate>Mon, 09 Jun 2008 17:11:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55208.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/55208.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/06/09/55208.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/55208.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/55208.aspx</trackback:ping><description>&lt;p&gt;繼承上一篇的願景【&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/05/07/3826.aspx"&gt;ASP.NET進階權限控管-Part 1 願景&lt;/a&gt;】,接著這篇先來講講一些基本的部分。&lt;/p&gt;&lt;p&gt;首先是【登入結合自己的資料庫】，以及【TreeView樹狀結構結合資料庫】這兩個部分，由於小喵以前已經有文章說明了這兩個部分，所以在這邊也不贅述。請看考以下的這兩篇。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/03/05/1237.aspx"&gt;登入結合自己的資料庫&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/03/05/1234.aspx"&gt;TreeView樹狀結構結合資料庫&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;瞭解了上面的這些部分候，接著就是如何維護樹狀結構，看一下維護運作的畫面先&lt;/p&gt;&lt;p&gt;&lt;a target="_blank" href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=menu002_2(1).jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="304" alt="menu002" width="563" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=menu002_thumb(1).jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;畫面分為左右兩區&lt;/p&gt;&lt;p&gt;左邊的【畫面選擇】會出現目前全部的樹狀結構，而右邊的【畫面設定】則是編輯區，用以新增、修改、刪除設定。另外在右邊裡面還有個相關aspx設定，用以設定哪些aspx歸屬於這個節點管理，未來系統會在運行的時候，自動抓取目前的畫面名稱，此時透過這個設定，找出要對應哪個節點代號，進而找出該節點的權限。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;再來就來看看如何設計這樣的畫面與程式。&lt;/p&gt;&lt;h3&gt;&lt;strong&gt;&lt;em&gt;資料庫設計&lt;/em&gt;&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;首先是資料庫欄位的設計，樹狀結構的資料庫欄位在&lt;a target="_blank" href="http://www.dotblogs.com.tw/topcat/archive/2008/03/05/1234.aspx"&gt;TreeView樹狀結構結合資料庫&lt;/a&gt;裡面已經有，再拿出來複習一下&lt;/p&gt;&lt;p&gt;資料表名稱：TCATMenu&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="/images/blog_blueshop_com_tw/topcat/590/r_TreeView001.gif" /&gt;&lt;/p&gt;&lt;p&gt;再來就是設計一個節點對畫面的資料表，格式如下：&lt;/p&gt;&lt;p&gt;資料表名稱：TCATMenuAspx&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=menu003_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="menu003" width="362" border="0" src="http://www.vcnet.tw/topcat/aspx?n=fle&amp;amp;r=menu003_thumb.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;畫面維護&lt;/h3&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;畫面維護上，TreeView產生過程稍微特別一點，小喵大致說明一下：&lt;/p&gt;&lt;p&gt;首先是在產生TreeView的遞迴程式方面，由於我們這次並非要產生一個具備超連結的TreeView，相對的，我們是要當點選TreeView的某個節點時，傳出該節點的NodeId，因此Node的NavigateUrl與Target就不給予指定。然後就可以在TreeView的事件TreeView1_SelectedNodeChanged去取得該Node的NodeId(Me.TreeView1.SelectedValue)，並且取得該NodeId的相關資料。&lt;/p&gt;&lt;p&gt;TreeView遞迴產生的部分請參考小喵以前的文章【&lt;a href="http://www.dotblogs.com.tw/topcat/archive/2008/03/05/1234.aspx"&gt;ASP.NET 2.0 使用資料表動態產生TreeView的樹狀結構&lt;/a&gt;】&lt;/p&gt;&lt;p&gt;AddNote的部分修改如下&lt;/p&gt;&lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;Function&lt;/span&gt; AddNodes(&lt;span class="kwrd"&gt;ByRef&lt;/span&gt; Dt &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable, &lt;span class="kwrd"&gt;ByRef&lt;/span&gt; tNode &lt;span class="kwrd"&gt;As&lt;/span&gt; TreeNode, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; PId &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
        &lt;span class="rem"&gt;'******** 遞迴增加樹結構節點 ********&lt;/span&gt;
        &lt;span class="kwrd"&gt;Try&lt;/span&gt;

            &lt;span class="rem"&gt;'定義DataRow承接DataTable篩選的結果&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rows() &lt;span class="kwrd"&gt;As&lt;/span&gt; DataRow
            &lt;span class="rem"&gt;'定義篩選的條件&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; filterExpr &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
            filterExpr = &lt;span class="str"&gt;&amp;quot;ParentId = &amp;quot;&lt;/span&gt; &amp;amp; PId
            &lt;span class="rem"&gt;'資料篩選並把結果傳入Rows&lt;/span&gt;
            rows = Dt.&lt;span class="kwrd"&gt;Select&lt;/span&gt;(filterExpr, &lt;span class="str"&gt;&amp;quot;Sort&amp;quot;&lt;/span&gt;)

            &lt;span class="rem"&gt;'如果篩選結果有資料&lt;/span&gt;
            &lt;span class="kwrd"&gt;If&lt;/span&gt; rows.GetUpperBound(0) &amp;gt;= 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;

                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; row &lt;span class="kwrd"&gt;As&lt;/span&gt; DataRow
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tmpNodeId &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Long&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tmpsText &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tmpsValue &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tmpsUrl &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tmpsTarget &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; NewNode &lt;span class="kwrd"&gt;As&lt;/span&gt; TreeNode
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rc &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;

                &lt;span class="rem"&gt;'逐筆取出篩選後資料&lt;/span&gt;

                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tt &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
                &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; row &lt;span class="kwrd"&gt;In&lt;/span&gt; rows
                    &lt;span class="rem"&gt;'放入相關變數中&lt;/span&gt;
                    tmpNodeId = row(&lt;span class="str"&gt;&amp;quot;NodeId&amp;quot;&lt;/span&gt;)
                    tmpsText = row(&lt;span class="str"&gt;&amp;quot;sText&amp;quot;&lt;/span&gt;) + &lt;span class="str"&gt;&amp;quot;(&amp;quot;&lt;/span&gt; + row(&lt;span class="str"&gt;&amp;quot;NodeId&amp;quot;&lt;/span&gt;).ToString + &lt;span class="str"&gt;&amp;quot;)&amp;quot;&lt;/span&gt;
                    tmpsValue = row(&lt;span class="str"&gt;&amp;quot;sValue&amp;quot;&lt;/span&gt;)
                    tmpsTarget = row(&lt;span class="str"&gt;&amp;quot;sTarget&amp;quot;&lt;/span&gt;)
                    tmpsUrl = row(&lt;span class="str"&gt;&amp;quot;sURL&amp;quot;&lt;/span&gt;)

                    &lt;span class="rem"&gt;'實體化新節點&lt;/span&gt;
                    NewNode = &lt;span class="kwrd"&gt;New&lt;/span&gt; TreeNode
                    &lt;span class="rem"&gt;'設定節點各屬性&lt;/span&gt;
                    NewNode.Text = tmpsText
                    NewNode.Value = tmpNodeId
                    &lt;span class="rem"&gt;'NewNode.NavigateUrl = tmpsUrl&lt;/span&gt;
                    &lt;span class="rem"&gt;'NewNode.Target = tmpsTarget&lt;/span&gt;
                    &lt;span class="rem"&gt;'If tmpsUrl = &amp;quot;&amp;quot; Then&lt;/span&gt;
                    &lt;span class="rem"&gt;'    NewNode.SelectAction = TreeNodeSelectAction.None&lt;/span&gt;
                    &lt;span class="rem"&gt;'End If&lt;/span&gt;
                    &lt;span class="rem"&gt;'將節點加入Tree中&lt;/span&gt;
                    &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.RunNodeText &amp;lt;&amp;gt; &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                        &lt;span class="kwrd"&gt;If&lt;/span&gt; tmpsText = &lt;span class="kwrd"&gt;Me&lt;/span&gt;.RunNodeText &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                            NewNode.&lt;span class="kwrd"&gt;Select&lt;/span&gt;()
                            &lt;span class="kwrd"&gt;Me&lt;/span&gt;.RunNodeText = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
                        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
                    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
                    tNode.ChildNodes.Add(NewNode)

                    &lt;span class="rem"&gt;'呼叫遞回取得子節點&lt;/span&gt;
                    rc = AddNodes(Dt, NewNode, tmpNodeId)

                &lt;span class="kwrd"&gt;Next&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="rem"&gt;'傳回成功訊息&lt;/span&gt;
            AddNodes = &lt;span class="str"&gt;&amp;quot;Success&amp;quot;&lt;/span&gt;

        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception
            lblErrMsg.Text = ex.Message
            AddNodes = &lt;span class="str"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;

        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;&lt;p&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;h3&gt;節點畫面對照&lt;/h3&gt;&lt;p&gt;另外就是，節點與畫面的對照，在TreeView的一個節點，他可能會用好幾個畫面才處理這個功能。因此NodeId與Aspx是一對多的關係。而畫面名稱可以用Page.ToString()取得，不過取得的名稱有點累贅，比如說，假設我的系統是&lt;a href="http://www.blueshop.com.tw/PCAT"&gt;http://www.blueshop.com.tw/PCAT&lt;/a&gt;&lt;/p&gt;&lt;p&gt;而有個ASPX他的是在我專案下Test資料夾下的PCATTest.aspx(&lt;a href="http://www.blueshop.com.tw/PCAT/Test/PCATTest.aspx"&gt;http://www.blueshop.com.tw/PCAT/Test/PCATTest.aspx&lt;/a&gt;)那麼取得的名子將是【aspx_test_pcattest_aspx】其中包含了前面固定會出現的aspx_，其他就是資料夾、檔案名稱，用_間隔開來。因此，小喵會把設定在TreeView的網址Test/PCATTest.aspx處理成test_pcattest_aspx這樣方便未來在PageBase裡面可以自動抓畫面名稱來判斷。處理的Function如下&lt;/p&gt;&lt;pre class="csharpcode"&gt;
Aspxs = Replace(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.txtAspx.Text.ToLower, &lt;span class="str"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;)
Aspxs = Replace(Aspxs, &lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;_&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;p&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;處理前：Test/PCATTest.aspx&lt;/p&gt;&lt;p&gt;處理後：test_pcattest_aspx&lt;/p&gt;&lt;p&gt;那麼在PageBase裡面只要用以下取得的拿來當作查詢條件就可以了&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Dim&lt;/span&gt; AspxName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = Mid(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.Page.ToString, 5, Len(&lt;span class="kwrd"&gt;Me&lt;/span&gt;.Page.ToString) - 4)&lt;/pre&gt;&lt;p&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;以上就是有關畫面樹狀結構設定、樹狀結構節點與畫面名稱對照設定的相關介紹。&lt;/p&gt;&lt;p&gt;接著下一篇將會介紹【&lt;a href="http://www.dotblogs.com.tw/topcat/archive/2008/06/09/4255.aspx"&gt;ASP.NET進階權限控管-Part 3 角色管理與角色使用者維護&lt;/a&gt;】&lt;/p&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/55208.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>topcat</dc:creator><title>ASP.NET進階權限控管-Part 1 願景</title><link>http://blog.blueshop.com.tw/topcat/archive/2008/05/08/54985.aspx</link><pubDate>Thu, 08 May 2008 13:45:00 GMT</pubDate><guid>http://blog.blueshop.com.tw/topcat/archive/2008/05/08/54985.aspx</guid><wfw:comment>http://blog.blueshop.com.tw/topcat/comments/54985.aspx</wfw:comment><comments>http://blog.blueshop.com.tw/topcat/archive/2008/05/08/54985.aspx#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://blog.blueshop.com.tw/topcat/comments/commentRss/54985.aspx</wfw:commentRss><trackback:ping>http://blog.blueshop.com.tw/topcat/services/trackbacks/54985.aspx</trackback:ping><description>&lt;P&gt;這個主題小喵一直以來一直想要做分享，但是又不知從何分享起，因為小喵的這套機制有點點複雜，他除了可以結合自定資料庫的使用者登入、角色概念外，還搭配了TreeView與資料庫結合，等等的技術。算是一個還蠻進階的運用。相關的介紹可能不是一兩篇Blog能夠介紹完。到底要多少篇小喵也不曉得...就從小喵希望達到的願景(事實上已經達到並上線使用中)開始介紹起。&lt;/P&gt;
&lt;P&gt;首先，要回憶一下往事先，小喵在ASP的時代，就寫了一個類似的權限控管機制，一樣是樹狀結構，可以針對每個使用者，設定每個畫面的【查詢、新增、修改、刪除】。相關的設定畫面如下圖：&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="" src="http://vip2.blueshop.com.tw/topcat/DemoTemp/TGDemo01.jpg" width=600&gt;&lt;/P&gt;
&lt;P&gt;小喵希望開發出來的權限控管機制，也是類似的狀況。但是以往的狀況有個缺點卻不得不提→組織異動，重新授權不易&lt;/P&gt;
&lt;P&gt;舉個例子來說，假設&lt;/P&gt;
&lt;P&gt;User甲&amp;nbsp;&amp;nbsp;&amp;nbsp; 有畫面(ABCD)的權限&lt;/P&gt;
&lt;P&gt;User乙&amp;nbsp;&amp;nbsp;&amp;nbsp; 有畫面(CDEF)的權限&lt;/P&gt;
&lt;P&gt;今天職務調整，讓這兩個人的職務對調&lt;/P&gt;
&lt;P&gt;此時，甲要→&lt;STRIKE&gt;AB&lt;/STRIKE&gt;,+EF。&amp;nbsp; 乙要→&lt;STRIKE&gt;EF&lt;/STRIKE&gt;，+AB&lt;/P&gt;
&lt;P&gt;其實，看起來，也沒什麼，就刪除4筆，增加4筆而已。不過如果細想一下，如果是跟User甲一樣狀況的有200人，那麼光是刪除、新增就頭大。而最常發生的，就是乙因為需要AB，所以申請+AB，不需要EF卻不申請刪除EF畫面權限，造成ABCDEF都有。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;因此...小喵希望能夠用【角色(身分)】來做管理，也就是畫面的權限設定，是依照不同的【角色(身分)】來授權，以剛剛的範例，就變成&lt;/P&gt;
&lt;P&gt;畫面-----角色(身分),&amp;nbsp;&amp;nbsp;&amp;nbsp; 角色(身分)-----使用者&lt;/P&gt;
&lt;P&gt;ABCD-----角色P,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 角色P-----User甲&lt;/P&gt;
&lt;P&gt;CDEF-----角色Q,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 角色Q----User乙&lt;/P&gt;
&lt;P&gt;這樣如果當兩邊職務調動的時候，其實只要動到【角色----使用者】這樣的資料就好，甚至未來擴編，有人要有相同的設定，也只需要把這個人設定適當的【角色】就能夠擁有該角色該有的畫面權限了。&lt;/P&gt;
&lt;P&gt;除此之外，一個人可以擁有多個角色，例如：一個人可能是【BlueShop的會員】，同時也是【ASP.NET討論區的版主】，因此當他是【BlueShop會員】這個角色時，就擁有【BlueShop會員】該擁有的畫面權限。 而同時，因為又兼具【ASP.NET討論區的版主】因此也擁有【ASP.NET討論區的版主】這角色應該有的畫面權限。&lt;/P&gt;
&lt;P&gt;例如：&lt;/P&gt;
&lt;P&gt;【BlueShop會員】:權限有畫面ABCD&lt;/P&gt;
&lt;P&gt;【ASP.NET討論區的版主】：權限有CDEF&lt;/P&gt;
&lt;P&gt;小喵身兼兩個身分，就有權限ABCDEF&lt;/P&gt;
&lt;P&gt;----&lt;/P&gt;
&lt;P&gt;授權上： &lt;BR&gt;一個角色可以有許多的使用者 &lt;BR&gt;一個使用者可以扮演許多的角色 &lt;BR&gt;授權時大致區分為查詢(可以點選進入)，拒絕(不可點選進入)，未設定(無該畫面的任何設定) &lt;BR&gt;依照角色來授權、以拒絕為優先、個人最優先 &lt;BR&gt;優先的先後順序為 &lt;BR&gt;個人設定&amp;gt;角色拒絕&amp;gt;角色設定 &lt;BR&gt;舉個例子 &lt;BR&gt;當一個畫面，小喵要進入時， &lt;BR&gt;小喵所屬的任何角色都沒有設定 &lt;BR&gt;→因為沒有任何設定可進入→不可進入 &lt;BR&gt;小喵所屬的角色中有一個可進、一個不可進 &lt;BR&gt;→因為以拒絕為優先→不可進入 &lt;BR&gt;小喵所屬的角色中有一個可進、無不可進 &lt;BR&gt;→因歸屬於該角色，且無任何拒絕→可進入 &lt;BR&gt;小喵所屬的角色中有一個可進，有一不可進，但個人設定為拒絕 &lt;BR&gt;→因個人設定為拒絕→不可進入 &lt;BR&gt;---------------------------------------------------------------------------------- &lt;BR&gt;這樣設計的目的是，畫面功能的設定，以角色設定為基本 &lt;BR&gt;如果沒有其他特別的條件，那麼就只需管好角色/使用者之間的關係 &lt;BR&gt;當有職務調動的時候，也只需調整使用者的【角色】就可以了一並設定好權限 &lt;BR&gt;當然世事往往不如意....會有少許例外的狀況 &lt;BR&gt;例外的狀況就以個人的方式設定，所以把個人設定的優先權設定為最高也是這個用意&lt;/P&gt;
&lt;P&gt;再仔細的整理一下規則，規則如下：&lt;/P&gt;
&lt;P&gt;&lt;TEXTAREA class=xml name=code rows=6 cols=50&gt; 

【瀏覽權限控管規則】：
於是就發展出目前小喵的權限控管規則
規則一：(角色管理)因應不同的職務需求，設定【角色】，可由許多使用者扮演相同的角色
規則二：(角色管理)一個【使用者】可以同時扮演許多不同的【角色】
規則三：(授權角色)設定權限時，依照【角色】的職務特性來設定
規則四：(拒絕優先)相同畫面中，當同時擁有的兩個以上【角色】有設定【拒絕】→以【拒絕】為優先
規則五：(個人最優先)當有個人【使用者】發生規則四狀況被拒絕，但右必須使用時→以【個人設定為最優先】

【查詢、新增、修改、刪除、列印權限】
規則一：先有瀏覽權限→再談這些設定(沒有權限瀏覽，一進畫面就被踢出，當然什麼也沒有)
規則二：所屬角色+使用者自己的設定中，只要其中有一可執行→就可執行
        例如小喵分屬RoleA,RoleB
        RoleA有查詢、新增、修改的權限
        RoleB有查詢、刪除的權限
        那麼小喵有的權限就是綜合起來的【新增(A)、修改(A)、刪除(B)】

【特殊角色：SysAdmin】
規則：擁有此角色的使用者，擁有最高的權限，任何畫面、任何功能均可使用
&lt;/TEXTAREA&gt;&lt;/P&gt;
&lt;P&gt;最後得到的畫面會是類似這樣：&lt;/P&gt;
&lt;P&gt;&lt;IMG alt="" src="http://vip2.blueshop.com.tw/topcat/DemoTemp/TGDemo02.gif" width=600&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;畫面驗證：&lt;/P&gt;
&lt;P&gt;用以上的這些規則來設定後，希望未來畫面能夠透過最簡單的方式，就能夠達到以下幾個動作&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;自動取得畫面名稱 
&lt;LI&gt;自動取得畫面的抬頭名稱 
&lt;LI&gt;驗證畫面是否有權限，沒權限者自動踢出登出 
&lt;LI&gt;取得畫面的各項權限設定(查詢、新增、修改、刪除、查詢、列印等) 
&lt;LI&gt;自動計算畫面使用次數(另有畫面可以查使用者、畫面使用次數累計)&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;以上就是小喵希望能夠達到的願景，畫面可以自己增減，權限可以動態設定，並且導入角色概念，以角色為主，個人為輔。並且一切都記錄在資料庫中。後面會陸續的說明，如何達到這樣的願景。&lt;/P&gt;&lt;img src ="http://blog.blueshop.com.tw/topcat/aggbug/54985.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>