代码之家  ›  专栏  ›  技术社区  ›  Damien_The_Unbeliever

我是否必须检查ApplyResponseChallengeSync中的响应状态?

  •  7
  • Damien_The_Unbeliever  · 技术社区  · 10 年前

    我写了一篇相当基本的 AuthenticationHandler<T> 派生类,用于为REST服务执行自定义身份验证。

    我以为(是的,我知道,坏主意) ApplyResponseChallengeAsync 只有当我确实需要应用我的挑战时才会被调用-例如,它被描述为:

    重写此方法以延迟( 碳化硅 )考虑到401挑战,如果所讨论的认证方案将认证交互作为其请求流的一部分进行处理。(如添加响应标头,或将登录页面或外部登录位置的401结果更改为302。)

    在我看来,只有在发放401的情况下,才会调用它。然而,在一些有限的测试中,我们看到一些例外情况如下:

    System.Web.HttpException (0x80004005): Server cannot append header after HTTP headers have been sent.
    at System.Web.HttpHeaderCollection.SetHeader(String name, String value, Boolean replace)
    at Microsoft.Owin.Host.SystemWeb.CallHeaders.AspNetResponseHeaders.Set(String key, String[] values)
    at Microsoft.Owin.Infrastructure.OwinHelpers.AppendHeader(IDictionary`2 headers, String key, String values)
    at OurAuthHandler.ApplyResponseChallengeAsync()
    at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<ApplyResponseCoreAsync>d__8.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.<TeardownAsync>d__5.MoveNext()
    --- And so on
    

    因此,为了调查这一点,我稍微更改了方法中的代码,以便可以使用调试器检查发生异常的情况:

    protected override Task ApplyResponseChallengeAsync()
    {
        try
        {
            foreach (var uri in Options.IdentityConfiguration.AudienceRestriction.AllowedAudienceUris)
            {
                Response.Headers.Append("WWW-Authenticate", "Bearer realm=\"" + uri + "\"");
            }
            return base.ApplyResponseChallengeAsync();
        }
        catch
        {
            throw; //Set a breakpoint here
        }
    }
    

    瞧,当我的断点被击中时,我看到 Response s状态代码为200/OK。

    问题

    所以,问题是,我是否必须自己检查状态代码,是否需要在某个地方传递/设置某个标志,以便只对401s调用此方法,还是我遗漏了其他内容?

    1 回复  |  直到 10 年前
        1
  •  4
  •   sloth JohnnBlade    10 年前

    是的,你必须自己检查状态码。该文件具有误导性。

    注意每个现有的 AuthenticationHandler s在 Katana project 同时检查状态代码:

    public class OpenIdConnectAuthenticationHandler : AuthenticationHandler<OpenIdConnectAuthenticationOptions>
    {
        ...
        protected override async Task ApplyResponseChallengeAsync()
        {
            if (Response.StatusCode == 401)
            {
                ....
            }
        }
        ...
    }
    

    internal class TwitterAuthenticationHandler : AuthenticationHandler<TwitterAuthenticationOptions>
    {
        ...
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "MemoryStream.Dispose is idempotent")]
        protected override async Task ApplyResponseChallengeAsync()
        {
            if (Response.StatusCode != 401)
            {
                return;
            }
        }
        ...
    }
    

    public class WsFederationAuthenticationHandler : AuthenticationHandler<WsFederationAuthenticationOptions>
    {
        ...
        protected override async Task ApplyResponseChallengeAsync()
        {
            if (Response.StatusCode == 401)
            {
                ...
            }
        }
        ...
    }
    

    我还检查了Katana项目的源代码:无法通过标记或其他方式改变这种行为。