【踩雷紀錄】MvcSiteMapProvider的Security Trimming

  • 297
  • 0

描述在使用MvcSiteMapProvider的Security Trimming遇到的問題

如果你想在ASP.NET MVC的專案中使用麵包屑與可能會調整網站連結的結構的話,MvcSiteMapProvider是個不錯的選擇
這篇文章不打算講怎麼怎麼使用與做基本教學(這種事情請自行google)
這篇文章想講的是我在Security Trimming+在MVC專案使用Identity遇到的問題
我先講一個情境吧
一個網站的功能通常會有不同的權限要求
權限足夠的人才能進入特定功能
權限不足的人當要進入時,理想的方式應該是只要內容的部分顯示權限不足
但是Menu與顯示登入者與登出等等部分應該還是要能正常顯示
為了達到這樣的效果,我寫了一個class繼承了AuthorizeAttribute,並override了HandleUnauthorizedRequest()
當使用者有登入但權限不足的時候,Redirect到指定的連結(客製的權限不足網頁)
我語法這樣用
filterContext.RequestContext.HttpContext.Response.Redirect("~/Error/NoPermission", true);
MVCSiteMap一般來說每個節點的設定都是在Mvc.sitemap這個xml檔中設定
理想上使用者只能看到有權限進入的Menu按鈕
雖然Mvc.sitemap能設定Roles
但是在官方的網頁有這樣一段話
「Comma-separated list of roles allowed to access the node and its child nodes. This attribute is for interoperability with non-MVC pages that are secured using ASP.NET forms authentication. For MVC, use the AuthorizeAttribute to provide security.」
我的理解是「使用MVC的話就不能這樣設,需要靠AuthorizeAttribute」
這不是Mvc.sitemap的XML設定一下,相關Controller的AuthorizeAttribute設一下就好
還要開一下Security Trimming(預設是關閉)
Security Trimming可以透過AuthorizeAttribute來決定顯示哪些Menu按鈕
我開了以後,程式一執行,_LoginPartial.cshtml的@Html.AntiForgeryToken()就拋出例外了
我連個首頁都看不到
我花了蠻多時間找問題在哪,後來發現問題跟Security Trimming有關
Security Trimming判斷權限不是直接看程式碼有沒有對Action限定Roles
而是會連過去試試看,看filterContext.Result的值,碰到權限不足的節點,一重新導向就出問題了
相關原文敘述:
「There is just one restriction - your implementation of AuthorizeAttribute must set the filterContext.Result property to null if it succeeds and set it to a non-null value if it fails. If you override the AuthorizeCore() method only, you are covered because the default implementation does this already. However, you must take this logic into account if you override the OnAuthorization() method.」
總結:
1.Security Trimming判斷權限的方式是連連看與看filterContext.Result,而不管你程式碼的語法
2.別像我一樣使用filterContext.RequestContext.HttpContext.Response.Redirect