从Asp.Net MVC上的拦截器调用Controller Action(Castle Windsor)

时间:2015-04-03 21:00:09

标签: asp.net-mvc-4 castle-windsor interceptor

有什么办法吗?我想调用带参数(或至少无参数)的动作,如下所示。

我的情况是;

Interceptor不包含来自MVC的任何引用,Interceptor位于ApplicationService层。 这是一个服务拦截器。

public class ControllerInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            var retVal = (ResponseDTOBase) invocation.ReturnValue;
            if (retVal.ResponseCode == UsrNotAuth)
            {
                //Invoke Controller Action With passsing parameter (retVal)
            }

            invocation.Proceed();
        }
    }

有什么想法吗?感谢。

1 个答案:

答案 0 :(得分:1)

我可以为您提供另一种请求授权方法。 MVC是其核心原则的状态机。状态机具有动作,触发器和警卫。在MVC中已经存在这样的“保护”,其目的是拦截控制器动作并检查用户权限。这是AuthorizeAttribute。该类实现IAuthorizationFilter。另一个方面是授权和身份验证应该在它们到达您的服务之前发生。我的意思是有两种类型的授权:

  1. 行动授权和
  2. 数据授权。
  3. 您可以使用AuthorizeAttribute实现的第一种授权或IAuthorizationFilter + FilterAttribute的自定义属性实现。以下是适用于ajax请求的SPA(单页应用程序)的此类属性的示例实现:

    属性:

    [AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public class LoggedOrAuthorizedAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            CheckIfUserIsAuthenticated(filterContext);
        }
    
        private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
        {
            // If Result is null, we’re OK: the user is authenticated and authorized. 
            if (filterContext.Result == null)
                return;
    
            // If here, you’re getting an HTTP 401 status code. In particular,
            // filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here. 
            // User is logged in but this operation is not allowed
            if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.HttpContext.Request.IsAjaxRequest())
            {
                //filterContext.HttpContext.Response.StatusCode = 401;
                JsonNetResult jsonNetResult = new JsonNetResult();
                jsonNetResult.Data = JsonUtils.CreateJsonResponse(ResponseMessageType.info, "msgOperationForbiddenYouAreNotInRole");
                filterContext.Result = jsonNetResult;
                //filterContext.HttpContext.Response.End();
            }
        }
    }
    

    如果您使用纯MVC,则有一个示例实现here。 用法:

    在您的控制器中

    [LoggedOrAuthorized(Roles = Model.Security.Roles.MyEntity.Create)]
    public ActionResult CreateMyEntity(MyEntityDto myEntityDto)
    {
    ...
    }
    

    您可以在每个控制器操作上应用此操作,并在到达控制器之前阻止用户。

    您可以通过过滤器内的Castle Windsor提供记录器和其他“管道”,以记录事件。

    在类似问题的this回答中提供了非常好的重要链接和评论。这些链接也为正确实施提供了很好的指导。

    其他类型的授权 - 可以在服务或控制器中处理数据访问授权。我个人更喜欢在管道中尽快处理各种授权。

    一般做法是不向用户显示他未授权查看或执行命令的任何数据或操作。当然,您必须仔细检查这一点,因为用户可以修改POST和GET请求。

    您可以通过将用户ID和实体ID传递给它来实现与实现IDataAccessService的简单接口并控制数据访问。

    重要的是,当用户未获得授权时,您不应该抛出异常,因为这根本不是例外。异常表示您的程序处于意外状态,禁止其正常执行。当用户未被授权时,这不是意料之外的事情 - 这是非常好的预期。这就是为什么在示例实现中返回消息而不是异常。

    另一个细微之处在于.NET框架对“异常”的处理方式不同,而且它们需要花费更多资源。这意味着您的站点将非常容易受到DDOS中断的影响,甚至可能无法执行。一般规则是,如果您通过例外控制您的预期程序流程,那么您没有正确地执行 - 重新设计就是治愈。

    我希望这可以指导您在您的方案中正确实施。

    请提供您想要实现的授权类型以及您手头的参数,以便我建议更具体的实施。