ASP.NET Core Web API / MVC 应用中 Cookie 日志记录中间件





5.00/5 (6投票s)
关于 Cookie 认证事件
引言
有时,我们需要记录 Cookie 日志,以便在开发站点或生产站点进行调试。我们遇到了类似的情况。
背景
在我们为 Android 客户端提供数据的大型 Web API 中,我们使用了身份验证进行客户端和服务器通信。应用程序的身份验证基于唯一生成的身份验证令牌。每当需要登录时,它都会自动发生。 有一次,我们的客户端提出了一个问题:**一个请求通过了身份验证,但紧随其后的对同一 URI 的下一个请求却失败了**。 我们在任何其他应用程序中都没有遇到过这种情况。 这个错误只发生在 200 多个设备中的一个或两个设备上。
然后我们开始调试会话。首先,我们验证了登录令牌是否有效,它是有效的,然后我们进入了流程的下一步。从任何角度来看,我们在业务方面所做的一切看起来都很好。我们不知道发生了什么。如果这个问题确实存在于 API 端,为什么只有**一个或两个设备出现问题,而不是全部?**
最后,我们开始调试我们收到的 cookie,因为身份验证仅基于 cookie,对吧。如果提交的 cookie 有效,则问题出在 API 端。如果 cookie 不是我们提供给他们的 cookie,那么问题出在应用程序端。为了进行此调试会话,我们开始分析如何记录 cookie。要了解/记录 cookie,我们需要了解以下详细信息
- 服务器在登录时生成的 Cookie
- 客户端在每个请求上提交的 Cookie
对于这个大问题,ASP.NET Core 提供了最佳解决方案。我们采用了
- Cookie 身份验证事件来了解生成的 cookie
- 中间件来了解提交的 cookie
Cookie 身份验证事件
允许订阅在 cookie 身份验证期间引发的事件。通过订阅 cookie 身份验证事件,我们可以了解 cookie 及其值。主要地,这个 cookie 身份验证事件有以下事件
RedirectToAccessDenied
RedirectToLogin
RedirectToLogout
RedirectToReturnURL
SigningIn
SignedIn
SignedOut
ValidatePrincipal
我们使用了 RedirectToAccessDenied
, SignedIn
, SigningIn
事件.
最终,我们的 CookieAuthenticationEvents
类看起来像这样
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Threading.Tasks;
namespace Web
{
public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
{
public override Task RedirectToAccessDenied
(RedirectContext<CookieAuthenticationOptions> context)
{
//Logging the required details
//Request Body has the client submitted cookie, if submitted
//Request available in the context. `context.HttpContext.Request`
return base.RedirectToAccessDenied(context);
}
public override Task SigningIn(CookieSigningInContext context)
{
//Logging the required details
return base.SigningIn(context);
}
public override Task SignedIn(CookieSignedInContext context)
{
//Logging the required details
//Generated new cookie information available here. In the request Body.
//Request available in the HttpContext. `context.HttpContext.Request`
return base.SigningIn(context);
}
}
}
我们需要提到这是一个 cookie 身份验证事件侦听器,对吧。这在定义 cookie 身份验证方案的地方完成。在我们的方法中,这是 *startup.cs* 类。此身份验证配置在 *startup.cs* 类的 ConfigureServices
部分下完成。 在 startup
类中的某个地方,我们肯定使用了类似下面的东西
public void ConfigureServices(IServiceCollection services)
{
...
services
.AddAuthentication()
.AddCookie("<Name Of the Authentication Scheme>", options =>
{
...
});
...
}
为了提及 CookieAuthenticationEvents
,我们将对上面的代码块进行以下更改
public void ConfigureServices(IServiceCollection services)
{
...
services
.AddAuthentication()
.AddCookie("", options =>
{
...
options.Events =
new MyCookieAuthenticationEvents(); // this is newly added line
});
...
}
现在,这将告诉我们生成了哪些 cookie 以及相关详细信息。
Cookie 日志记录中间件
我们分析的第二个重要部分是记录 cookie。为此,我们决定使用中间件。我们的 cookie 日志记录中间件看起来像
using System.Threading.Tasks;
namespace Web
{
public class MyCookieLogMiddleware
{
private readonly RequestDelegate _next;
public MyCookieLogMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next.Invoke(context);
//Logging the required details
//Submitted Cookies available in the request. `context.Request.Cookies`
//Generated or response cookies available in the response header.
// `context.Response.Headers["Set-Cookie"]`
)
}
}
为了使该中间件工作,我们必须将其添加到应用程序的 ApplicationBuilder
中,也可以通过 *startup.cs* 类实现。此 *Startup.cs* 类具有 Configure
方法。这可以通过具有中间件扩展轻松完成。
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseMyCookieLogMiddleware
(this IApplicationBuilder instance)
{
return instance.UseMiddleware<mycookielogmiddleware>();
}
}
最后,在 *startup.cs* 中
public void Configure(IApplicationBuilder app,
IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseAuthentication();
app.UseCookieLogMiddleware(); //this is the line we have to include.
...
app.UseMvc();
}
此 cookie 日志记录中间件应存在于 UseAuthentication
和 UseMvc
中间件定义之间。 完成! 现在尝试记录 cookie。
注意事项
身份验证 cookie 是更敏感的信息。如果任何人获取此信息,那么我们将遇到麻烦,因此请注意这一点。不要永久启用它,也不要在第三方可以访问的任何公共场所记录/写入 cookie。
结论
此技巧可能对正在寻找解决方案以记录服务器生成的 cookie 以及客户端应用程序提交的 cookie 的人有所帮助。 感谢您的阅读!
历史
- 2021年6月30日: 初始版本