In my ASP .NET Core 3.1 MVC app, I use endpoint routing like so
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "access",
pattern: "access/",
defaults: new { controller = "Home", action = "Access" });
});
So browsing to /access, launches the Access action, where the app checks if user complies with some access requirements.
if (access checks...)
{
return View();
}
Now I would prefer having this check in a custom middleware (or possibly a custom authorize attribute) instead of having it in the Controller. So my question to you is, how should I rewrite the UseEndPoints call, to include a custom middleware for the /access area?
You could do this using authorization policies. Configure these in your Startup.cs
inside ConfigureServices(IServiceCollection services)
like so:
services.AddAuthorization(options =>
{
// Create your own policy and make the "access checks" in there
options.AddPolicy("MyAccessPolicy", policy => policy.RequireAssertion(httpCtx =>
{
if (access checks...)
return true;
else
return false;
}));
});
Then you simply decorate your controller action with the Authorize
attribute like so:
[Authorize(Policy = "MyAccessPolicy")]
public IActionResult Access()
{
return View();
}
Now, whenever you try to go to /access
this policy will run, and if the policy returns false, the user will be met with an HTTP 403 (Forbidden) status code.
In response to your comment here's an example of a middleware and how to map it to a specific route.
An example from my own project with a global error handling middleware (some irrelevant parts stripped out):
public class ExceptionHandlingMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
// Call next middleware
await next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
ErrorDetails error = null;
if (ex is FileNotFoundException || ex is DirectoryNotFoundException)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
error = _localizer.FilesOrFoldersNotFound();
}
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(
new CustomResponse(false, error ?? _localizer.DefaultError()),
_serializerSettings));
}
}
To only use this middleware for specific routes you could do as suggested here:
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Map("path/where/error/could/happen",
b => b.UseMiddleware<ExceptionHandlingMiddleware>());
// ...
}
Or check the path inside the middleware itself:
// ExceptionHandlingMiddleware.cs
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (!context.Request.Path.StartsWithSegments("path/where/error/could/happen"))
{
// Skip doing anything in this middleware and continue as usual
await next(context);
return;
}
// Use middleware logic
try
{
// Call next middleware
await next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With