Пользовательское промежуточное ПО (или авторизация) для заданного c маршрута в ASP. NET Core 3.1 MVC - PullRequest
0 голосов
/ 14 апреля 2020

В моем приложении ASP. NET Core 3.1 MVC я использую маршрутизацию конечной точки следующим образом:

        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" });
        });

Поэтому при переходе к / access запускается действие Access, при котором приложение проверяет, пользователь соответствует некоторым требованиям к доступу.

if (access checks...)
{
    return View();
}

Теперь я бы предпочел иметь эту проверку в пользовательском промежуточном программном обеспечении (или, возможно, в пользовательском атрибуте авторизации), а не в контроллере. Поэтому мой вопрос к вам: как мне переписать вызов UseEndPoints, чтобы включить пользовательское промежуточное ПО для области / access?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Расширение политики авторизации [Authorize]

Это можно сделать с помощью политик авторизации. Настройте их в вашем Startup.cs внутри ConfigureServices(IServiceCollection services) следующим образом:

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;
    }));
});

Затем вы просто декорируете действие вашего контроллера с атрибутом Authorize следующим образом:

[Authorize(Policy = "MyAccessPolicy")]
public IActionResult Access()
{
    return View();
}

Теперь, всякий раз, когда вы пытаетесь выполнить go - /access, эта политика будет выполняться, и если политика вернет false, пользователь встретится с кодом состояния HTTP 403. (Запрещено).

Пользовательское промежуточное ПО, сопоставленное с маршрутом

В ответ на ваш комментарий приведен пример промежуточного программного обеспечения и его сопоставление с указанным c маршрутом.

Пример из моего собственного проекта с глобальным промежуточным программным обеспечением для обработки ошибок (некоторые не имеют отношения к делу). детали удалены):

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));
        }
    }

Чтобы использовать это промежуточное ПО только для определенных c маршрутов, которые вы могли бы сделать , как предлагается здесь :

// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Map("path/where/error/could/happen",
        b => b.UseMiddleware<ExceptionHandlingMiddleware>());
    // ...
}

Или проверьте Путь внутри самого промежуточного программного обеспечения:

// 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);
    }
}
0 голосов
/ 14 апреля 2020

Вы можете расширять AuthorizeAttribute вместе с IAuthorizationFilter в Asp. Net Core

1.Создайте класс, который расширяет AuthorizeAttribute, это будет использоваться поверх контроллера или действия как Asp. Net встроенный в ядро ​​атрибут [Authorize].

2. Реализация метода OnAuthorization(AuthorizationFilterContext context), являющегося частью интерфейса IAuthorizationFilter.

3.Call return ключевое слово без каких-либо дополнительных действий для авторизованного пользователя.

4.Установите AuthorizationFilterContext результат как Неавторизованный для неавторизованных пользователей как context.Result = new UnauthorizedResult()

    public class SampleAuthorizePermission : AuthorizeAttribute, IAuthorizationFilter
{
    public string Permissions { get; set; }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (string.IsNullOrEmpty(Permissions))
        {
            context.Result = new UnauthorizedResult();
            return;
        }

        var userName = context.HttpContext.User.Identity.Name;

        var assignedPermissionsForUser =
            MockData.UserPermissions
                .Where(x => x.Key == userName)
                .Select(x => x.Value).ToList();

        var requiredPermissions = Permissions.Split(",");
        foreach (var x in requiredPermissions)
        {
            if (assignedPermissionsForUser.Contains(x))
                return;
        }

        context.Result = new UnauthorizedResult();
        return;
    }
}

и в вашем контроллере

[SampleAuthorizePermission(Permissions = "CanRead")]
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return "value";
    }
...