我用谷歌搜索并叠加了这个问题以及它的不同变体,但我仍然感到困惑,如果它可能的话。我只想为具有特定属性的所有操作添加自定义标头。听起来很简单?但事实并非如此。我刚刚写了以下内容:
[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
始终具有更高的优先级。你可以同意这很难看。
怎么做?
答案 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属性,然后在响应时添加标题。