換句話說,這是一個非常愚蠢的想法嗎?如何創建特定於區域,控制器和操作的自定義AuthorizeAttribute?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// get the area, controller and action
var area = filterContext.RouteData.Values["area"];
var controller = filterContext.RouteData.Values["controller"];
var action = filterContext.RouteData.Values["action"];
string verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}/{2}/{3}", area, controller, action, verb);
// set role name to area/controller/action name
this.Roles = roleName;
base.OnAuthorization(filterContext);
}
}
UPDATE 我試圖避免以下,在我們有極其精細的角色權限,因爲角色是在每個客戶端的基礎設置和連接到用戶羣的情景:
public partial class HomeController : Controller
{
[Authorize(Roles = "/supplierarea/homecontroller/indexaction/")]
public virtual ActionResult Index()
{
return View();
}
[Authorize(Roles = "/supplierarea/homecontroller/aboutaction/")]
public virtual ActionResult About()
{
return View();
}
}
任何人都可以啓發我一個安全的方式來編寫這個AuthorizeRouteAttribute來訪問路由信息並將其用作角色名稱嗎?正如列維所說,RouteData.Values不安全。
是否使用執行httpContext.Request.Path更安全或更好的做法?
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
return;
}
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}", path, verb);
if (!filterContext.HttpContext.User.IsInRole(roleName))
{
// role auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
// P.S. I want to tell the logged in user they don't
// have access, not ask them to login. They are already
// logged in!
return;
}
//
base.OnAuthorization(filterContext);
}
這也許說明了問題遠一點:
enum Version
{
PathBasedRole,
InsecureButWorks,
SecureButMissingAreaName
}
string GetRoleName(AuthorizationContext filterContext, Version version)
{
//
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// recommended way to access controller and action names
var controller =
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action =
filterContext.ActionDescriptor.ActionName;
var area = "oh dear...."; // mmmm, where's thearea name???
//
var insecureArea = filterContext.RouteData.Values["area"];
var insecureController = filterContext.RouteData.Values["controller"];
var insecureAction = filterContext.RouteData.Values["action"];
string pathRoleName =
String.Format("{0}/{1}", path, verb);
string insecureRoleName =
String.Format("{0}/{1}/{2}/{3}",
insecureArea,
insecureController,
insecureAction,
verb);
string secureRoleName =
String.Format("{0}/{1}/{2}/{3}",
area,
controller,
action,
verb);
string roleName = String.Empty;
switch (version)
{
case Version.InsecureButWorks:
roleName = insecureRoleName;
break;
case Version.PathBasedRole:
roleName = pathRoleName;
break;
case Version.SecureButMissingAreaName:
// let's hope they don't choose this, because
// I have no idea what the area name is
roleName = secureRoleName;
break;
default:
roleName = String.Empty;
break;
}
return roleName;
}
請你可以添加到你的答案,以顯示你的建議如何在代碼中工作?我們正在使用區域,所以它需要反映這一點以及控制器和操作。出於興趣,你真的可以匹配一個控制器或行動(即建議:/ myarea/mycontroller/myaction'; DROP TABLE members; - /)?毫無疑問,MVC不會與首先與控制器或操作相匹配? – Junto 2011-02-03 21:24:11
解決您的問題的更新迴應。 – Levi 2011-02-04 00:22:29