【发布时间】: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