我正在编写一个用于Hmac身份验证的自定义Owin中间件AuthenticationHandler。
在重写'AuthenticateCoreAsync'方法中,我需要读取请求的http标头和'Body'(内容)。
我有一切工作,索赔/身份验证票等。
但每当我访问或使用IOwinRequest.Body时,我的WebApi控制器都会中断。它们被正确调用,但所有api方法参数都是'null'。好像身体内容在某个地方丢失了。
我尝试将IOwinRequest.Body复制到内存流并使用它,我尝试使用IOwinRequest.Body.Seek(0)等重置它,但都无济于事。
我找不到关于如何使用Body of 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;
}
答案 0 :(得分: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现在已经在管道中的正确位置注册了。