ASP.NET MVC提供了AuthorizeAttribute,可用來控制Controller Action的安全性,但由於該屬性所指定的角色或使用者是寫在代碼中而不是在設定檔中的,因而不夠靈活。
為能夠更靈活、更細粒度地控制許可權,需要某種方法能夠在設定檔(如web.config)中定義許可權,這樣才能在不需要重新編譯代碼的情況下,通過修改設定檔即可改變應用程式的授權。一個簡單的情境,[CustomAuthorize(Roles = "Manager")] ,與系統內建的[Authorize(Roles = "Manager")] ,區別在於:後面的許可權控制是通過Membership Provider完成的,即目前使用者有沒有許可權是通過Context.User.IsInRole("Managers")來判斷的;第一個則是自訂ActionFilter通過讀取配置項來完成許可權控制的。
廢話不說,上代碼:
1. 從系統內建的AuthorizeAttribute繼承(請注意:AuthorizeAttribute本身是從FilterAttribute繼承且實現IAuthorizationFilter介面):
public class CustomAuthorizeAttribute : AuthorizeAttribute {
......
}
2. override其中關鍵的一個方法:AuthorizeCore
1 protected override bool AuthorizeCore(HttpContextBase httpContext) {
2 ...
3 }
4
5 private static bool UserInRole(string role) {
6 if (user.IsInRole(role))
7 return true;
8 return false;
9 }
3. 實現自訂授權:
protected override bool AuthorizeCore(HttpContextBase httpContext) {
if (httpContext == null){
throw new ArgumentNullException("httpContext");
}
IPrincipal user = httpContext.User;
if (!user.Identity.IsAuthenticated) {
return false;
}
var rolesInSetting = ConfigurationManager.AppSettings["RolesFor:" + Roles];
var usersInSetting = ConfigurationManager.AppSettings["UsersFor:" + Users];
if (!String.IsNullOrEmpty(usersInSetting)) {
var users = usersInSetting.Split(newchar[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (users != null|| users.Length > 0 && users.Contains(User.Identity.Name, StringComparer.OrdinalIgnoreCase))
return true;
}
if (String.IsNullOrEmpty(rolesInSetting))
returnfalsevar roles = rolesInSetting.Split(newchar[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (roles ==null|| roles.Length <=0)
returnfalse;
if (roles.Any(t => UserInRole(t))
returntrue;
returnfalse}
4. 設定檔 web.config
<add key="RolesFor:Manager" value="admins, managers"/>
<add key="UsersFor:Manager" value="hackee,bill"/>
5. 配置Action方法:
[CustomAuthorize(Manager)]
public ActionResult GetSecureData() { ... }