在身份验证过滤器中的ChallengeAsync方法的上下文中设置结果

Bad*_*dri 6 asp.net-web-api asp.net-mvc-5 asp.net-web-api2

这个问题与我在这里提供的答案有关.OP的评论让我思考了一下.我建议在身份验证过滤器IHttpActionResultChallengeAsync方法中使用类似这样的类.

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
                                  CancellationToken cancellationToken)
{
    context.Result = new ResultWithChallenge(context.Result);
    return Task.FromResult(0);
}

public class ResultWithChallenge : IHttpActionResult
{
    private readonly IHttpActionResult next;

    public ResultWithChallenge(IHttpActionResult next)
    {
        this.next = next;
    }

    public async Task<HttpResponseMessage> ExecuteAsync(
                                CancellationToken cancellationToken)
    {
        var response = await next.ExecuteAsync(cancellationToken);
        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            response.Headers.WwwAuthenticate.Add(
                   new AuthenticationHeaderValue("Basic", "realm=localhost"));
        }

        return response;
    }
}
Run Code Online (Sandbox Code Playgroud)

而不是这个,我可以简化ChallengeAsync这个.

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
                             CancellationToken cancellationToken)
{
    var result = await context.Result.ExecuteAsync(cancellationToken);
    if (result.StatusCode == HttpStatusCode.Unauthorized)
    {
        result.Headers.WwwAuthenticate.Add(
                     new AuthenticationHeaderValue("Basic", "realm=localhost"));
    }
    context.Result = new ResponseMessageResult(result);
}
Run Code Online (Sandbox Code Playgroud)

这使我免于创建一个类实现,IHttpActionResult但这是正确的方法吗?我感到一种不安的感觉,从性能的角度来看,这有点不好,因为我感觉我正在将动作结果转换为HttpResponseMessage并返回到动作结果.任何关于需要在这里实现IHttpActionResult像我建议的单独类的指针将被赞赏,而不是使用上面的代码.

dma*_*son 7

目的是使用第一种方法而不是第二种方法.例如,请参阅基本身份验证示例(也可用于MVC),该示例遵循第一种方法:http: //aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/BasicAuthentication/ReadMe.txt

第二种方法大多有效.我不会太担心表现的立场; 无论哪种方式,你分配一个动作结果对象和一个响应消息对象,所以我没有看到太大的区别.

但是,我推荐第一种方法有几个原因:

  1. 第二种方法在MVC中的工作方式不同.MVC和Web API都有身份验证过滤器,它们的工作方式基本相同.但是在MVC中,没有与ResponseMessageResult等效的(HttpContext根据需要进行更新,而不是返回一个HttpResponseMessage,可以由每个调用者在堆栈中替换).如果你有一个身份验证过滤器的MVC实现,你可能最终会在那里做第一个方法.
  2. 它略微改变了管道行为的意图.ChallengeAsync中的代码早于上下文中的代码运行.它返回的结果.例如,如果代码更改了HttpRequestMessage上的属性并且影响了后来的过滤器的ChallengeAsync逻辑,则行为可能与预期的不同.

该框架肯定可以使界面更容易实现; 随时对此工作项进行投票:https: //aspnetwebstack.codeplex.com/workitem/1456