public class AuditAttribute : ActionFilterAttribute
{
//Our value to handle our AuditingLevel
public int AuditingLevel { get; set; }
protected DateTime start_time;
protected int auditID { get; set; }
protected readonly IAuditRepository _repository;
public AuditAttribute(IAuditRepository repository)
{
this._repository = repository;
this.AuditingLevel = 3;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
start_time = DateTime.Now;
//Stores the Request in an Accessible object
var request = filterContext.HttpContext.Request;
TimeSpan duration = (DateTime.Now - start_time);
string controller = (string)filterContext.RouteData.Values["controller"];
string action = (string)filterContext.RouteData.Values["action"];
//Generate the appropriate key based on the user's Authentication Cookie
//This is overkill as you should be able to use the Authorization Key from
//Forms Authentication to handle this.
string sessionIdentifier = null;
if (request.Cookies[".AspNetCore.Identity.Application"] != null)
{
sessionIdentifier = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(request.Cookies[".AspNetCore.Identity.Application"])).Select(s => s.ToString("x2")));
}
string userId = null;
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
userId = filterContext.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
}
//Generate an audit
AuditModel audit = new AuditModel()
{
SessionID = sessionIdentifier,
IPAddress = request.HttpContext.Connection.RemoteIpAddress.ToString(),
URLAccessed = Microsoft.AspNetCore.Http.Extensions.UriHelper.GetDisplayUrl(request),
TimeAccessed = DateTime.UtcNow,
UserID = userId,
UserName = filterContext.HttpContext.User.Identity.Name ?? "Anonymous",
Data = SerializeRequest(request),
Duration = duration,
Controller = controller,
Action = action,
};
//Stores the Audit in the Database
var id = _repository.Add(audit);
// Достъп до полето се осъществява чрез RouteData.Values["AuditID"];
auditID = id;
if (!filterContext.RouteData.Values.ContainsKey("AuditID"))
{
filterContext.RouteData.Values.Add("AuditID", id);
}
else
{
filterContext.RouteData.Values["AuditID"] = id;
}
base.OnActionExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
TimeSpan duration = (DateTime.Now - start_time);
var audit = _repository.GetById(auditID);
audit.Duration = duration;
_repository.Edit(audit);
base.OnResultExecuted(filterContext);
}
//This will serialize the Request object based on the level that you determine
private string SerializeRequest(HttpRequest request)
{
switch (AuditingLevel)
{
//No Request Data will be serialized
case 0:
default:
return "";
//Basic Request Serialization - just stores Data
case 1:
return JsonConvert.SerializeObject(new { request.Cookies, request.Headers });
//Middle Level - Customize to your Preferences
case 2:
return JsonConvert.SerializeObject(new { request.Cookies, request.Headers, request.QueryString });
//Highest Level - Serialize the entire Request object
case 3:
//We can't simply just Encode the entire request string due to circular references as well
//as objects that cannot "simply" be serialized such as Streams, References etc.
//return Json.Encode(request);
return JsonConvert.SerializeObject(new { request.Cookies, request.Headers, request.QueryString });
}
}
}