从中间件中排除控制器
Exclude Controller from Middleware
我写了一个中间件,它检查授权令牌是否包含在 header 中,并根据该请求执行,如果缺少令牌,则会出现 returns 错误。现在它对其他控制器工作正常。
但是我应该为不需要授权 header 的 Login/Registration 控制器做什么。我如何配置我的中间件来忽略这些。
用于检查 Headers 授权令牌的中间件的当前实现。
public class AuthorizationHeaderValidator
{
private readonly RequestDelegate _next;
private readonly ILogger<AuthorizationHeaderValidator> _logger;
public AuthorizationHeaderValidator(RequestDelegate next, ILogger<AuthorizationHeaderValidator> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
StringValues authorizationHeader;
Console.WriteLine(context.Request.Path.Value);
if (context.Request.Headers.TryGetValue("Authorization", out authorizationHeader))
{
await _next(context);
}
else
{
_logger.LogError("Request Failed: Authorization Header missing!!!");
context.Response.StatusCode = 403;
var failureResponse = new FailureResponseModel()
{
Result = false,
ResultDetails = "Authorization header not present in request",
Uri = context.Request.Path.ToUriComponent().ToString(),
Timestamp = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
Error = new Error()
{
Code = 108,
Description = "Authorization header not present in request",
Resolve = "Send Request with authorization header to avoid this error."
}
};
string responseString = JsonConvert.SerializeObject(failureResponse);
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(responseString);
return;
}
}
}
不确定为什么需要中间件来验证授权 header 是否存在。很难以这种方式排除控制器,因为所有请求在到达 MVC 管道之前都会经过这个中间件。
[Authorize]
属性将为您完成这项工作,前提是您集成了某种形式的身份验证。如果您需要排除不需要授权的控制器,您只需在控制器级别或操作方法级别添加 [AllowAnonymous]
即可。请参阅下面来自 Microsoft Docs
的代码片段
[Authorize]
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult Login()
{
}
public ActionResult Logout()
{
}
}
如果必须使用中间件,可以考虑将其用作MVC 过滤器,这意味着它将作用域限定为MVC 管道。更多详情,请看这里link。但是,这仍然不能解决排除控制器而不添加一些复杂逻辑的问题,这可能会非常复杂。
这不是完整的答案,只是指示。为下一代完成此任务后,请post你的代码。
您似乎需要一个过滤器而不是中间件,因为中间件无法访问路由数据。通过继承 Attribute 并实现 IAuthorizationFilter 或 IAsyncAuthorizationFilter 创建新的授权过滤器。只有一种实现方法
public void OnAuthorization(AuthorizationFilterContext context)
{
}
或
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
}
用 AllowAnonymousAttribute 修饰控制器 and/or 要从该逻辑中排除的操作。在您的 OnAuthorization 方法中检查当前操作或控制器是否具有 AllowAnonymousAttribute 以及它是否为 return 而无需在 AuthorizationFilterContext 上设置结果。否则执行原始中间件的逻辑并设置结果 属性。设置结果将使过滤器管道的其余部分短路。
然后全局注册你的过滤器:
services.AddMvc(options =>
{
options.Filters.Add(new CustomAuthorizeFilter());
});
我已经通过实施 PipeLine 解决了我的问题
public class AuthorizationMiddlewarePipeline
{
public void Configure(IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseMiddleware<AuthorizationHeaderValidator>();
}
}
而且我在 Controller Scope 或 Method scope 上这样使用它
[MiddlewareFilter(typeof(AuthorizationMiddlewarePipeline))]
我写了一个中间件,它检查授权令牌是否包含在 header 中,并根据该请求执行,如果缺少令牌,则会出现 returns 错误。现在它对其他控制器工作正常。 但是我应该为不需要授权 header 的 Login/Registration 控制器做什么。我如何配置我的中间件来忽略这些。
用于检查 Headers 授权令牌的中间件的当前实现。
public class AuthorizationHeaderValidator
{
private readonly RequestDelegate _next;
private readonly ILogger<AuthorizationHeaderValidator> _logger;
public AuthorizationHeaderValidator(RequestDelegate next, ILogger<AuthorizationHeaderValidator> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
StringValues authorizationHeader;
Console.WriteLine(context.Request.Path.Value);
if (context.Request.Headers.TryGetValue("Authorization", out authorizationHeader))
{
await _next(context);
}
else
{
_logger.LogError("Request Failed: Authorization Header missing!!!");
context.Response.StatusCode = 403;
var failureResponse = new FailureResponseModel()
{
Result = false,
ResultDetails = "Authorization header not present in request",
Uri = context.Request.Path.ToUriComponent().ToString(),
Timestamp = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
Error = new Error()
{
Code = 108,
Description = "Authorization header not present in request",
Resolve = "Send Request with authorization header to avoid this error."
}
};
string responseString = JsonConvert.SerializeObject(failureResponse);
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(responseString);
return;
}
}
}
不确定为什么需要中间件来验证授权 header 是否存在。很难以这种方式排除控制器,因为所有请求在到达 MVC 管道之前都会经过这个中间件。
[Authorize]
属性将为您完成这项工作,前提是您集成了某种形式的身份验证。如果您需要排除不需要授权的控制器,您只需在控制器级别或操作方法级别添加 [AllowAnonymous]
即可。请参阅下面来自 Microsoft Docs
[Authorize]
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult Login()
{
}
public ActionResult Logout()
{
}
}
如果必须使用中间件,可以考虑将其用作MVC 过滤器,这意味着它将作用域限定为MVC 管道。更多详情,请看这里link。但是,这仍然不能解决排除控制器而不添加一些复杂逻辑的问题,这可能会非常复杂。
这不是完整的答案,只是指示。为下一代完成此任务后,请post你的代码。
您似乎需要一个过滤器而不是中间件,因为中间件无法访问路由数据。通过继承 Attribute 并实现 IAuthorizationFilter 或 IAsyncAuthorizationFilter 创建新的授权过滤器。只有一种实现方法
public void OnAuthorization(AuthorizationFilterContext context)
{
}
或
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
}
用 AllowAnonymousAttribute 修饰控制器 and/or 要从该逻辑中排除的操作。在您的 OnAuthorization 方法中检查当前操作或控制器是否具有 AllowAnonymousAttribute 以及它是否为 return 而无需在 AuthorizationFilterContext 上设置结果。否则执行原始中间件的逻辑并设置结果 属性。设置结果将使过滤器管道的其余部分短路。 然后全局注册你的过滤器:
services.AddMvc(options =>
{
options.Filters.Add(new CustomAuthorizeFilter());
});
我已经通过实施 PipeLine 解决了我的问题
public class AuthorizationMiddlewarePipeline
{
public void Configure(IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseMiddleware<AuthorizationHeaderValidator>();
}
}
而且我在 Controller Scope 或 Method scope 上这样使用它
[MiddlewareFilter(typeof(AuthorizationMiddlewarePipeline))]