本文介绍了在身份验证过滤器中的 ChallengeAsync 方法的上下文中设置结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与我在此处提供的答案有关.OP的评论让我思考了一下.我建议在身份验证过滤器的 ChallengeAsync 方法中使用一个实现 IHttpActionResult 的类.

This question is related to the answer I have provided here. OP's comment got me thinking a bit. I suggested using a class implementing IHttpActionResult like this in the ChallengeAsync method of the authentication filter.

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;
    }
}

代替这个,我可以像这样简化ChallengeAsync.

Instead of this, I can simplify the ChallengeAsync like this.

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);
}

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

This saves me from creating a class implementing IHttpActionResult but is this the right way? I get an uneasy feeling that this is somehow bad from a performance standpoint because it feels like I'm converting action result to HttpResponseMessage and back to action result. Any pointers on the need for a separate class here implementing IHttpActionResult like what I suggested will be appreciated as against using the code above.

推荐答案

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

The intent was to use the first approach rather than the second. For example, see the Basic Authentication sample (also available for MVC), which follows the first approach:http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/BasicAuthentication/ReadMe.txt

第二种方法大多有效.我不会太在意性能的观点;无论哪种方式,您都分配了一个操作结果对象和一个响应消息对象,所以我看不出有太大区别.

The second approach mostly works. I wouldn't be too concerned about the performance standpoint; either way you're allocating one action result object and one response message object, so I'm not seeing much difference there.

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

However, there are a couple of reasons I'd recommend the first approach:

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

该框架肯定可以使接口的实现更容易;随意对这个工作项目投票:https://aspnetwebstack.codeplex.com/workitem/1456

The framework definitely could make it easier to implement the interface; feel free to vote on this work item:https://aspnetwebstack.codeplex.com/workitem/1456

这篇关于在身份验证过滤器中的 ChallengeAsync 方法的上下文中设置结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-17 06:34
查看更多