有条件地使用自定义中间件

syn*_*ror 4 asp.net-core-mvc asp.net-core

我在 asp 中创建了我的自定义身份验证中间件。net core 项目,并注册如下:

public class MyAuthenticationMidleware
{
    private readonly RequestDelegate _next;

    public ConnectAuthenticationMidleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (!UserIsAuthenticated())
        {
            context.Response.StatusCode = 401;
            return;
        }
        ...
        await _next.Invoke(context);
    }
}

public static class MyAuthenticationMidlewareExtensions
{
    public static IApplicationBuilder UseMyAuthentication(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyAuthenticationMidleware>();
    }
}
Run Code Online (Sandbox Code Playgroud)

在启动中:

    public void Configure(...)
    {
        app.UseStaticFiles();
        app.UseMyAuthentication();
        app.UseMvc();
    }
Run Code Online (Sandbox Code Playgroud)

这可以正常工作 - 为每个请求运行身份验证中间件。如果用户未通过身份验证,则返回 401。否则将调用特定的 mvc 操作。

我试图做的是阻止身份验证中间件针对某些特定操作运行。我使用MapWhenmethod 创建了另一个扩展方法,并按如下方式使用它:

public static class MyAuthenticationMidlewareExtensions
{
    public static IApplicationBuilder UseMyAuthentication(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<MyAuthenticationMidleware>();
    }

    public static IApplicationBuilder UseMyAuthenticationWhen(this IApplicationBuilder builder, Func<HttpContext, bool> predicate)
    {
        return builder.MapWhen(predicate, applicationBuilder => applicationBuilder.UseMyAuthentication());
    }
}

public void Configure(...)
{
    app.UseStaticFiles();
    app.UseMyAuthenticationWhen(context => context.Request.Path != "xyz");
    app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不能按预期工作。仅当路径与“xyz”不同时才调用中间件,但它似乎使整个链短路 - 没有调用特定于 mvc 的操作或过滤器。

可能我的理解MapWhen有误。有什么办法可以得到我想要的结果吗?

Ton*_*y D 6

MapWhen创建一个新的管道分支时,将附带谓词是真实的,那支也没有用,你有主枝归队UseMvc()

您可以将扩展方法更改为使用UseWhen而不是MapWhen. UseWhen 重新加入主管道,以便您UseMvc()仍然会被调用。

注意:虽然上面的链接引用了 aspnet-contrib,但UseWhen扩展方法现在是Microsoft.AspNetCore.Http.Abstractions 的一部分。

这允许您UseMvc()在您的Configure方法中保持明确,而不是隐藏在您的身份验证扩展方法中,它实际上没有任何业务。


ade*_*lin 1

MapWhen用于分离中间件管道。如果你想使用mvc作为分支管道,你需要单独添加。所以你应该.UseMvc();在扩展方法中使用如下所示:

public static IApplicationBuilder UseMyAuthenticationWhen(this IApplicationBuilder builder, Func<HttpContext, bool> predicate)
{
    return builder.MapWhen(predicate, applicationBuilder =>
    { 
        applicationBuilder.UseMyAuthentication();
        applicationBuilder.UseMvc();
    });
}
Run Code Online (Sandbox Code Playgroud)

不过我不会走你的路。对于身份验证中间件,我将实现自己的中间件,例如Mongodb 数据存储的 asp.net core 中基于简单令牌的身份验证/授权,并使用Authorize属性进行授权 mvc 操作。