考虑在我的许多控制器操作中重新出现的以下代码块。 (我主要关注方法体的前6行)。
[HttpGet]
public ActionResult OptOut()
{
var user = this.SecurityPrincipal;
if (user.IsReadOnlyUser)
{
this.TempData["ViewModel"] = new AuthorizationModel { User = user };
return this.RedirectToAction("NotAuthorized", "Authorization");
}
var model = /* Elided for brevity */
return this.View(model);
}
我的控制器派生自基类SecuredController
,而基类又来自Controller
。 SecurityPrincipal
是SecuredController
的属性,包含有关当前用户的大量Active Directory数据。
为了消除重复的代码,我理想地希望将if {...}
块中包含的功能移动到基类方法中,但我无法想到任何方法所以,因为方法的返回类型必须是ActionResult
,所以会产生类似这样的东西:
if ((var result = this.RequireReadWrite()) != null)
{
return result;
}
任何人都可以建议一种方法来做到这一点,还是我在这里运气不好?
答案 0 :(得分:2)
正如评论中所述,特别注意安全性是cross cutting concern我们建议在您的使用案例和设计中使用MVC Action Filters。
Microsoft的文档内容非常丰富,网上有关于如何使用 MVC过滤器的更多示例。我将尝试提供一个示例,但这将基于对您的软件架构的许多假设,因为我根本就不了解它。
您可以创建以下类:
public class SecuredFilterAttribute : AuthorizeAttribute
{
...
}
如果使用Dependency Injection框架,您可以注入SecurityPrincipal
服务。但我再一次不知道你的应用程序的架构,所以由你如何创建这种依赖
覆盖AuthorizeCore
时,您可以像这样实现它:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return !this.SecurityPrinciple.IsReadOnlyUser;
}
未经授权时,覆盖HandleUnauthorizedRequest
方法重定向:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var redirectRoute = ...; //your route to redirect to an unauthorized page
filterContext.Result = new RedirectToRouteResult(redirectRoute);
//do some other things, for example, setting some tempdata information
}
再次由您决定如何使用此过滤器。您可以在全球注册,也可以在每个控制器或操作的基础上应用它。要在您的创业公司全球注册:
GlobalFilters.Filters.Add(new SecuredFilterAttribute());