我需要通过JWT为.NET Core Web API创建自定义身份验证,但要求客户端希望在HTTP请求的正文中发送令牌。
这不是标准方法,.NET Core默认也不支持此方法。有没有一种方法可以从HTTP请求主体获取令牌并将其用于身份验证。
我目前所依赖的内容是Request.EnableRewind()
,并使用MemoryStream
从主体中读取内容,然后再次寻找主体的起始位置,以便以后可以由控制器读取。效果很好,但是如果在短时间内有成千上万的请求,则API的性能将下降,这是不好的。
这种方法是否有很好的替代方法?
services.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = true;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
RequireExpirationTime = true,
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = ctx =>
{
StringValues values;
if (ctx.Request.Method.Equals("POST"))
{
ctx.Request.EnableRewind();
using (var ms = new MemoryStream())
{
ctx.Request.Body.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
ctx.Request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms))
{
var jsonBody = reader.ReadToEnd();
var body = JsonConvert.DeserializeObject<BaseRequest>(jsonBody);
ctx.Token = body.Token;
ctx.Request.Headers["Authorization"] = $"Bearer {body.Token}";
}
return Task.CompletedTask;
}
}
return Task.CompletedTask;
}
};
});
答案 0 :(得分:1)
由于您要求使用MemoryStream
的替代方法,因此也许可以使用Request.EnableBuffering()
。我建议在devblogs.microsoft.com上检查“ Re-reading ASP.Net Core request bodies with EnableBuffering()”。
基本上,您的OnMessageReceived
看起来像这样:
if (ctx.Request.Method.Equals("POST")
{
ctx.Request.EnableBuffering();
using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, $YOURBUFFERSIZE$, true))
{
var jsonBody = reader.ReadToEnd();
var body = JsonConvert.DeserializeObject<BaseRequest>(jsonBody);
if (body != null)
{
ctx.Token = body.Token;
ctx.Request.Headers["Authorization"] = $"Bearer {body.Token}";
ctx.Request.Body.Position = 0;
}
}
}
坦白说,这本身并不是最好的方法,但是如果您真的想避免修改OnMessageReceived
以外的任何内容,那么我想这种方法不需要使用MemoryStream