我正在为 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;
}