使用 IAuthenticationFilter 时 HttpContext.Current 为空

Posted

技术标签:

【中文标题】使用 IAuthenticationFilter 时 HttpContext.Current 为空【英文标题】:HttpContext.Current is null when using IAuthenticationFilter 【发布时间】:2019-03-25 15:50:26 【问题描述】:

我正在使用ng-file-upload 上传文件,并且在使用IAuthenticationFilter 时遇到了一些异常问题,因为HttpContext.Current 为空。当我在WebApiConfig 中评论身份验证过滤器时,一切正常。

要测试的控制器

    [HttpPost]
    public IHttpActionResult Upload()
    
        var current = HttpContext.Current;
        if (current == null)
        
            return Content(HttpStatusCode.BadRequest, Logger.Error("HttpContext.Current is null"));
                    

        if (current.Request != null && current.Request.Files != null)
        
            var file = current.Request.Files.Count > 0 ? current.Request.Files[0] : null;
            if (file != null)
            
                file.SaveAs(@"C:\Temp\test.csv");
            
        
        return Content(HttpStatusCode.BadRequest, Logger.Error("Should not reach here"));
    

IAuthenticationFilter

public class KeyAuthentication : Attribute, IAuthenticationFilter

    // we only want to apply our authentication filter once on a controller or action method so return false:
    public bool AllowMultiple
    
        get  return false; 
    

    // Authenticate the user by apiKey
    public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
                
        HttpRequestMessage request = context.Request;

        string apiKey = ExtractApiKey(request);
        bool IsValidCustomer = await ValidateKey(apiKey);
        if (IsValidCustomer)
        
            var currentPrincipal = new GenericPrincipal(new GenericIdentity(apiKey), null);
            context.Principal = principal;                
        
        else
        
             context.ErrorResult = new ErrorMessageResult("Missing API Key");
        
    

    // We don't want to add challange as I am using keys authenticaiton
    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
      
        return Task.FromResult(0);
    

提取 API 密钥

public static string ExtractApiKey(HttpRequestMessage request)

    if (!request.Headers.TryGetValues("x-api-key", out IEnumerable<string> keys))
return string.Empty;

    return keys.First();

【问题讨论】:

不要使用或将您的代码耦合到HttpContext.Current。如果这是ApiController,则需要更改使用的方法。 如何从客户端发布文件 能分享一下ExtractApiKey的方法吗?我敢打赌,您已经在该方法中提取了请求正文——这将导致请求正文在移动到请求管道中的下一个处理程序时变为null @Svek 不,我只是在提取标题。更新了上面的代码。发现了一些有趣的东西,如果我从 AuthenticateAsync 方法中删除“异步”,代码工作正常。所以,似乎 IIS 正在改变它的线程,HttpContext 在两者之间丢失。当不使用 async/await 时,一切都在那里。 其实你的await在方法中在哪里呢?通常,您会有类似IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken); 的声明 【参考方案1】:

解决方案是在 web.config 中包含 @Alfredo 评论的“targetFramework=4.5”,https://***.com/a/32338414/3973463 中包含更多详细信息

【讨论】:

以上是关于使用 IAuthenticationFilter 时 HttpContext.Current 为空的主要内容,如果未能解决你的问题,请参考以下文章

IAuthenticationFilter 中的 C# Ninject Web API 异步查询导致实体框架中的多个操作错误

ASP.NET MVC 控制器通过继承控制器来达到 过滤 并且多了一个IAuthenticationFilter

DbContext 在使用异步任务方法时被释放

Asp Web Api 生命周期问题

验证(Authentication)和授权(Authorization):

如果我有一个来自Web API 2项目的身份验证过滤器,我可以在WCF服务中重用它吗?