3

我们的应用程序具有 a 的概念PermissionAttribute。该属性在我们应用程序的基础层中定义,我们的命令和查询都使用该属性进行修饰。由于这个属性是在基础层中定义的,我们不能(也不想)让它继承FilterAttribute或实现System.Web.Mvc.IActionFilter它。

我们仍然希望将此属性应用于控制器操作,如下所示:

[Permission(Permissions.Administration.ManageUsers)]
public ActionResult Index()
{
    return this.View();
}

基于此属性,应应用适当的安全检查。我一直在浏览 MVC 代码库以找到合适的挂钩来自定义 MVC 行为,以允许基于此自定义属性添加这些安全检查。我虽然关于创建一个从其方法ControllerActionInvoker返回一个自定义的自定义,该自定义将返回基于 的存在而创建的自定义,但感觉工作量很大,我不确定这是正确的行走路径.ReflectedControllerDescriptorGetControllerDescriptorFilterAttributePermissionAttribute

什么是定制 MVC 管道以便我们可以处理这个非 MVC 相关属性的有效和愉快的方式?

4

2 回答 2

2

我会这样做。首先创建自己的实现,AuthorizeAttribtues如下所示:

public class PermissionAuthoriseAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //Leaving the implementation of this to you, but you check if your
        //PermissionAttribute is assigned and call it's methods.
        if(...)
            return true;

        //You may want to check this first, depending on your requirements
        return base.AuthorizeCore(httpContext);
    }
}

然后通过将此行添加到FilterConfig.cs文件中来将其应用于您的项目:

filters.Add(new PermissionAuthoriseAttribute());
于 2014-09-17T10:27:37.657 回答
2

我最终做了以下事情:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
        filters.Add(new PermissionAuthorizationFilter(
            () => Global.Container.GetInstance<IUserPermissionChecker>()), 0);
        filters.Add(new HandleErrorAttribute());
    }
}

public sealed class PermissionAuthorizationFilter : IAuthorizationFilter
{
    private readonly Func<IUserPermissionChecker> userPermissionCheckerFactory;

    public PermissionAuthorizationFilter(
        Func<IUserPermissionChecker> userPermissionCheckerFactory) {
        this.userPermissionCheckerFactory = userPermissionCheckerFactory;
    }

    public void OnAuthorization(AuthorizationContext filterContext) {
        var attribute = filterContext.ActionDescriptor
            .GetCustomAttributes(typeof(PermissionAttribute), true)
            .OfType<PermissionAttribute>()
            .SingleOrDefault();

        if (attribute != null) {
            VerifyPermission(filterContext, attribute.PermissionId);
        }
    }

    private static void VerifyPermission(AuthorizationContext filterContext,
        Guid permissionId) {
        var permissionChecker = userPermissionCheckerFactory.Invoke();

        if (!permissionChecker.HasPermission(permissionId))
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}
于 2014-09-17T10:40:12.947 回答