在MVC中为Action添加自定义标头

时间:2017-06-26 13:41:14

标签: c# .net asp.net-mvc action-filter

我用谷歌搜索并叠加了这个问题以及它的不同变体,但我仍然感到困惑,如果它可能的话。我只想为具有特定属性的所有操作添加自定义标头。听起来很简单?但事实并非如此。我刚刚写了以下内容:

[AttributeUsage(AttributeTargets.Method)]
public class HelloWorldAttribute : ActionFilterAttribute
{
    /// <inheritdoc />
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Headers["X-HelloWorld"] = string.Empty;
    }
}

它适用于所有请求,除非在[Authorize]级别被Controller禁止。

我尝试将此属性用于Controller级别,并传递必须将此标题添加到其中的方法的名称,但它也不起作用。似乎Authorize始终具有更高的优先级。你可以同意这很难看。

怎么做?

2 个答案:

答案 0 :(得分:1)

您可以编写自己的授权属性,并在注释自动化时处理您的代码,或者您可以添加Policy

哦,我太懒了......

这里的例子

首先添加政策

public class ReplaceHeaderPolicy : IAuthorizationRequirement
{

}

public class ReplaceHeaderHandler : AuthorizationHandler<ReplaceHeaderPolicy>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ReplaceHeaderPolicy requirement)
    {

        if (!context.User.Identity.IsAuthenticated)
        { 
            var fc = (FilterContext)context.Resource;
            fc.HttpContext.Response.Headers["X-HelloWorld"] = string.Empty;
        }

        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

然后注册您的政策

services.AddAuthorization(options =>
        {
            options.AddPolicy("ReplaceHeader",
                              policy => policy.Requirements.Add(new ReplaceHeaderPolicy()));
        });

        services.AddSingleton<IAuthorizationHandler, ReplaceHeaderHandler>();

并在控制器上使用它

[Authorize]
    [Authorize(Policy = "ReplaceHeader")]
    public IActionResult Index()
    {
        return View();
    }

删除第二个[授权]以允许访问未授权访问

我希望这有帮助

答案 1 :(得分:1)

问题是Authorize属性是防止控制器方法实际运行的,所以你的其他属性永远不会被运行。

您可以添加像这样的自定义属性

public class HandleUnauthorizedAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if (filterContext.Exception.GetType() != typeof(SecurityException)) return;

        var controllerName = (string)filterContext.RouteData.Values["controller"];
        var actionName = (string)filterContext.RouteData.Values["action"];
        var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

        filterContext.Result = new ViewResult
        {
            ViewName = "Unauthorized",
            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = 403;
        filterContext.HttpContext.Response.Headers.Add("X-HelloWorld", "");
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

将处理将从Authorize属性抛出的安全异常。

或者您可以编写自定义的Authorize属性,然后在响应时添加标题。