C# 仅在具有Authorize属性的端点上有条件地使用中间件

C# 仅在具有Authorize属性的端点上有条件地使用中间件,c#,asp.net-core,middleware,asp.net-core-identity,C#,Asp.net Core,Middleware,Asp.net Core Identity,我已经编写了一个中间件,我只想在经过身份验证的端点上运行它 因此,基本上我希望在我的实现中,它只在控制器或操作标记为[Authorize]时触发。任何不需要授权的控制器操作都不应该要求我的中间件触发 我发现了UseWhen功能,但我管理的最好的功能是,中间件仅在用户经过身份验证后才会触发。但是,在用户登录后,if仍将在所有端点上触发 这是我目前的条件 app.UseWhen(context => context.User.Identity.IsAuthenticated,

我已经编写了一个中间件,我只想在经过身份验证的端点上运行它

因此,基本上我希望在我的实现中,它只在控制器或操作标记为
[Authorize]
时触发。任何不需要授权的控制器操作都不应该要求我的中间件触发

我发现了UseWhen功能,但我管理的最好的功能是,中间件仅在用户经过身份验证后才会触发。但是,在用户登录后,if仍将在所有端点上触发

这是我目前的条件

        app.UseWhen(context => context.User.Identity.IsAuthenticated, appBuilder =>
        {
            appBuilder.UseAutomaticallyRefreshTokenMiddleware();
        });

我想我只需要更改上下文检查,但不确定用什么替换它。

中间件将根据条件注册到管道中,并且注册仅在启动时完成。之后不会修改注册。一旦它们成为管道的一部分,它们就是管道的一部分。您可以做的一件事是自定义Authorize属性。继承Authorize属性,然后在该属性中运行您在中间件中运行的逻辑。

ASP.NET Core 3.0通过端点路由实现了这一点,在此之前无法完成,因为路由决策和端点选择要比中间件管道运行时晚得多。

根据您的要求,您可以尝试
IActionFilter
而不是中间件

  • TokenRefrehFilter

    public class TokenRefrehFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
        }
    
        public void OnActionExecuting(ActionExecutingContext context)
        {
            //check whether action is authorized attribute
            var isAuthorizedAction = context.Filters.Any(f => f.GetType() == typeof(AuthorizeFilter));
        }
    }
    
  • 注册
    TokenRefrehFilter

    services.AddMvc(options => {
        options.Filters.Add(typeof(TokenRefrehFilter));
    })
    SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
    对于这种方式,
    TokenRefrehFilter
    将针对控制器请求运行,您可以使用
    True
    检查
    isAuthorizedAction
    ,以了解重新格式化令牌所需的操作


  • 在应用程序设置中,此时似乎没有指向匹配控制器的路径。您可以创建一个自定义控制器,如
    RefreshingController
    ,并将其标记为
    Authorize
    ,然后从
    RefreshingController
    派生控制器。您应该实现
    OnActionExecuting
    方法来刷新那里的令牌。
    OnActionExecuting
    是正确的重写方法。您能澄清一下您的用例吗?如果用户已登录,为什么不能在中间件中添加一个跳过中间件逻辑的条件呢?感谢您到目前为止对Saarrr和theMayer的输入。只是给你一些背景。我使用的是带有刷新令牌的OIDC混合流。如果用户位于需要授权的端点上,此中间件将检查当前会话中的访问令牌。如果即将到期,该中间件将执行一个反向通道刷新令牌请求。这只需要在授权端点上触发。公共端点不应运行此中间件,因为用户可能尚未登录,如果预期令牌尚未出现,它将开始返回401个公共端点。您好,Shazad,谢谢您的输入。考虑到您描述的管道顺序,我认为您的建议可能是我的做法。我会把这件事留到明天再做,以征求其他建议。