【问题标题】:.NET Core Token authentication - body.NET Core 令牌身份验证 - 正文
【发布时间】:2020-02-05 19:40:57
【问题描述】:

我需要通过 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;
        }
    };
});

【问题讨论】:

    标签: authentication .net-core jwt asp.net-core-webapi


    【解决方案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

    【讨论】:

      猜你喜欢
      • 2018-08-03
      • 2021-01-13
      • 2017-10-30
      • 2019-02-22
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 2018-12-17
      相关资源
      最近更新 更多