.NET MVC中ValidateAntiForgeryToken校验失败后如何记录表单信息?
Great question! The default ValidateAntiForgeryTokenAttribute throws an HttpAntiForgeryException before your action method even runs when the token is missing or invalid—that’s why your code inside the Login method never gets executed. Let’s walk through two solid approaches to capture and log that form data:
This approach lets you target specific actions (like your Login endpoint) and keeps the logging logic tightly tied to the anti-forgery validation process.
Create a custom attribute inheriting from
ValidateAntiForgeryTokenAttribute
Override theOnAuthorizationmethod to catch validation failures, log the form data, then rethrow the exception to preserve the original security behavior:using System.Web.Mvc; using System.Web.Helpers; using System.Diagnostics; using System.Linq; public class LoggingValidateAntiForgeryTokenAttribute : ValidateAntiForgeryTokenAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { try { // Run the default anti-forgery validation check base.OnAuthorization(filterContext); } catch (HttpAntiForgeryException ex) { // Capture all form data from the request var formData = filterContext.HttpContext.Request.Form; string formattedFormData = string.Join("; ", formData.AllKeys // Exclude sensitive fields like passwords from logs! .Where(key => !key.Equals("Password", System.StringComparison.OrdinalIgnoreCase)) .Select(key => $"{key}={formData[key]}")); // Replace with your actual logging mechanism (e.g., database, file, logging framework) Debug.WriteLine($"Anti-forgery validation failed. Request form data: {formattedFormData}"); // Example with a logging framework like Serilog: // Log.Warning(ex, "Anti-forgery check failed for POST request. Form data: {FormData}", formattedFormData); // Re-throw the exception to ensure the invalid request is rejected (returns 400 Bad Request) throw; } } }Swap the default attribute on your action
Replace the standard[ValidateAntiForgeryToken]with your custom logging attribute:[HttpPost, LoggingValidateAntiForgeryToken] public ActionResult Login(LoginViewModel model) { // Your existing login logic remains unchanged }
If you want to log all anti-forgery failures across your entire application, you can handle the exception in Global.asax.cs:
using System; using System.Web; using System.Web.Helpers; using System.Diagnostics; using System.Linq; protected void Application_Error(object sender, EventArgs e) { var exception = Server.GetLastError(); var antiForgeryException = exception as HttpAntiForgeryException; if (antiForgeryException != null && HttpContext.Current.Request.HttpMethod == "POST") { var request = HttpContext.Current.Request; var formData = request.Form; string formattedFormData = string.Join("; ", formData.AllKeys .Where(key => !key.Equals("Password", System.StringComparison.OrdinalIgnoreCase)) .Select(key => $"{key}={formData[key]}")); // Log the captured form data Debug.WriteLine($"Global anti-forgery failure detected. Form data: {formattedFormData}"); } // Leave this line in to let the framework handle the error response (or remove if you want a custom response) // Server.ClearError(); }
Critical Notes:
- Security First: Never log sensitive data like passwords, credit card numbers, or personal identifiers. Always exclude these fields from your logged form content as shown in the examples.
- Preserve Security Behavior: Always rethrow the
HttpAntiForgeryExceptionafter logging (in the custom filter) to ensure invalid requests are rejected, maintaining your application's security posture.
内容的提问来源于stack exchange,提问作者user7747014

