1

我正在为 Hmac 身份验证编写自定义 Owin 中间件 AuthenticationHandler。

在覆盖的“AuthenticateCoreAsync”方法中,我需要读取请求的 http 标头和“正文”(内容)。

我有一切工作,索赔/身份验证票等。

但是每当我访问或使用 IOwinRequest.Body 做某事时,我的 WebApi 控制器就会中断。它们被正确调用,但所有 api 方法参数都是“null”。好像正文内容在某个过程中丢失了。

我尝试将 IOwinRequest.Body 复制到内存流并使用它,我尝试使用 IOwinRequest.Body.Seek(0) 等重置它,但均无济于事。

我也找不到任何关于如何使用 IOwinRequest 正文的好的示例/文档。

任何人都可以指出我正确的方向吗?

在下面的代码中,当我留下评论时它会起作用。当我取消注释这些行以实际进行身份验证(并从 Body 读取)时,我的 webapi 方法接收所有空参数。

internal class HMacAuthenticationMiddleware : AuthenticationMiddleware<HMacAuthenticationOptions>
{
    private readonly ILogger logger;

    public HMacAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, HMacAuthenticationOptions options)
        : base(next, options)
    {
        this.logger = app.CreateLogger<HMacAuthenticationMiddleware>();
    }

    protected override AuthenticationHandler<HMacAuthenticationOptions> CreateHandler()
    {
        return new HMacAuthenticationHandler(this.logger);
    }
}

HMacAuthenticationHandler:

    protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
    {
        string[] apiKeys = null;
        AuthenticationTicket authenticationTicket = null;
        if (this.Request.Headers.TryGetValue(Configuration.ApiKeyHeader, out apiKeys))
        {
            ////var bufferedStream = await CreateStreamBuffer(Request);
            //var memStream = new MemoryStream();
            //await new StreamContent(Request.Body).CopyToAsync(memStream);
            //Request.Body = memStream;
            //memStream.Seek(0, SeekOrigin.Begin);
            //var httpMessage = Request.CreateRequestMessage(new StreamContent(memStream));
            //var authHandler = new HMacInnerAuthenticationHandler(httpMessage, Options);
            //var isAuthenticated = await authHandler.IsAuthenticated();
            //Request.Body.Seek(0, SeekOrigin.Begin);

            var isAuthenticated = true;
            if (isAuthenticated)
            {
                var userName = this.Options.UsernameLookup.GetByApiKey(apiKeys.First());
                var identity = new ClaimsIdentity(
                    new[]
                        {
                            new Claim(ClaimTypes.NameIdentifier, apiKeys.First(), XmlSchemaString, this.Options.AuthenticationType),
                            new Claim(ClaimTypes.Name, userName, XmlSchemaString, this.Options.AuthenticationType)
                        },
                    this.Options.AuthenticationType,
                    ClaimsIdentity.DefaultNameClaimType,
                    ClaimsIdentity.DefaultRoleClaimType);

                authenticationTicket = new AuthenticationTicket(identity, null);
            }
        }
        return authenticationTicket;
    }
4

1 回答 1

2

好的,所以在挖掘了 aspnetweb 堆栈源之后。特别是在这里:https ://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Http.Owin/WebApiAppBuilderExtensions.cs

我注意到我没有使用该方法将 WebApi 注册到 owin。

我仍在使用“GlobalConfiguration.Configure(WebApiConfig.Register);” 在 Global.asax.cs 中

我删除了它,将其替换为:

        var httpConfig = new HttpConfiguration();
        WebApiConfig.Register(httpConfig);
        app.UseWebApi(httpConfig);

在 Startup.cs 中,以及其他中间件。

现在一切正常,因为我猜 WebApi 现在已在管道中的正确位置注册。

于 2014-02-08T00:21:53.080 回答