【问题标题】:How to deal with null HttpContext.Current when using auth filters with async/await?使用带有异步/等待的身份验证过滤器时如何处理 null HttpContext.Current?
【发布时间】:2015-11-25 16:08:30
【问题描述】:

在我的控制器中的一个 api 中,我需要引用 HttpContext.Current。在我实现自定义身份验证过滤器之前,一切正常。过滤器使用带有等待的异步方法。但是,使用过滤器后,HttpContext.Current 在到达我的控制器时为空。

我假设这是因为我的控制器由于异步/等待而在以前的不同线程上执行在过滤器中。
如果是这种情况,我应该如何访问控制器中的“原始”上下文?
这有点令人失望,因为过滤器似乎是一个很好的可插拔想法,但不幸的是它们带有一些 [严重] 缺点。
示例伪代码:

public class TestAuthFilter : Attribute, IAuthenticationFilter
{
    private static string validationClaim = "testClaim";
    private tokenValidationUri;

    public bool AllowMultiple { get { return false; } }

    public TestAuthFilter(string tokenValidationUri)
    {
        this.tokenValidationUri = tokenValidationUri;
    }

    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        // We are not adding any authentication challenges to the response
        return Task.FromResult(0);
    }

    public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        HttpRequestMessage request = context.Request;
        AuthenticationHeaderValue authorization = request.Headers.Authorization;

        if (authorization == null)
        {
            return;
        }

        if (authorization.Scheme != "Bearer")
        {
            return;
        }

        if (String.IsNullOrEmpty(authorization.Parameter))
        {
            context.ErrorResult = new AuthenticationFailureResult("Missing access token", request);
            return;
        }

        string token = authorization.Parameter;
        IPrincipal principal = await AuthenticateAsync(token, cancellationToken);
        if (principal == null)
        {
            context.ErrorResult = new AuthenticationFailureResult("Invalid access token", request);
        }
        else
        {
            context.Principal = principal;
        }
    }

    public async Task<IPrincipal> AuthenticateAsync(string token, CancellationToken cancellationToken)
    {
        using (HttpClient client = new HttpClient())
        {
            try
            {                    
                HttpResponseMessage response = await client.GetAsync(tokenValidationUri + token, cancellationToken);

                using (HttpContent content = response.Content)
                {
                    string result = await content.ReadAsStringAsync();
                    if (result != null)
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            var success = await response.Content.ReadAsAsync<TokenValidationSuccess>();
                            if (success.audience.Equals(validationAudience, StringComparison.Ordinal))
                            {
                                TestPrincipal principal = new TestPrincipal([...]);
                                return principal;
                            }
                        }
                        else
                        {
                            var error = await response.Content.ReadAsAsync<TokenValidationError>();
                        }
                    }
                }
            }
            catch (HttpRequestException e)
            {
                Debug.WriteLine("Exception: {0}", e.Message);
            }
        }
        return null;
    }
}



如有任何建议,我将不胜感激。
谢谢。

【问题讨论】:

  • 将上下文作为参数传递。
  • 如何将上下文作为参数传递给我的控制器?这意味着我应该能够在某个时候获取“原始”上下文,然后将其传递给控制器​​。但是,我的控制器的方法是由框架调用的。能详细点吗?
  • 您能提交您的自定义过滤器吗?
  • 你的AuthenticationFilter 必须有OnAuthentication() 方法。能不能也提交一下。还有你在哪里打电话HttpContext.Current我在你的代码中找不到它。
  • @bdristan:您的目标是 .NET 4.5,和您是否在您的web.config 中将httpRuntime@targetFramework 设置为4.5?

标签: asp.net-mvc asp.net-web-api asp.net-web-api2


【解决方案1】:

解决方案是在 web.config 中包含“targetFramework=4.5”。致谢 Stephen Cleary - 见上面的 cmets。

【讨论】:

    【解决方案2】:

    这是AuthenticateAsyncWebAPI 上的一个很好的链接:http://www.asp.net/web-api/overview/security/authentication-filters

    应该将HttpAuthenticationContext作为参数,其中包含ActionContext和HttpRequestMessage请求的线程安全版本。

    这是到达那里的继承链:

    (HttpRequestMessage)System.Web.Http.Filters.HttpAuthenticationContext.ActionContext.ControllerContext.Request
    

    【讨论】:

      猜你喜欢
      • 2020-03-06
      • 2020-07-25
      • 2015-12-20
      • 2018-07-27
      • 2019-09-17
      • 2016-03-25
      • 2017-09-29
      • 1970-01-01
      • 2017-11-09
      相关资源
      最近更新 更多