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

时间:2016-10-05 06:57:51

标签: asp.net-core asp.net-core-mvc

我在asp中创建了自定义身份验证中间件。净核心项目,并将其注册如下:

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

在初创公司:

    public void Configure(...)
    {
        app.UseStaticFiles();
        app.UseMyAuthentication();
        app.UseMvc();
    }

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

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

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

不幸的是,这并没有像预期的那样奏效。只有当路径与&#34; xyz&#34;不同时才会调用中间件,但似乎它会短路整个链 - 不会调用mvc特定的操作或过滤器。

我对MapWhen的理解可能不正确。有没有办法得到我想要的结果?

2 个答案:

答案 0 :(得分:3)

MapWhen在提供的谓词为true时创建一个新的管道分支,并且该分支与您拥有UseMvc()的主分支重新加入。

您可以将扩展方法更改为使用UseWhen而不是MapWhenUseWhen Eigen Tensors README,以便您的UseMvc()仍会被调用。

  

注意:虽然上面的链接引用了aspnet-contrib,但UseWhen扩展方法现在是rejoins with the main pipeline的一部分。

这样,您就可以在UseMvc()方法中明确保留Configure,而不是隐藏在您的身份验证扩展方法中,而这种方法确实没有业务。

答案 1 :(得分:0)

MapWhen用于分隔中间件管道。如果您想将mvc用于branced管道,则需要单独添加。因此,您应该在扩展方法中使用.UseMvc();,如下所示:

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

然而我不会按你的方式行事。对于身份验证中间件,我会实现自己的中间件,如Simple token based authentication/authorization in asp.net core for Mongodb datastore,并使用Authorize属性进行授权mvc操作。