使用中间件记录网站访问日志记录

发布时间:2021-04-28

对于网站访问日志的记录,一般情况下都是使用现有的日志服务,比如谷歌分析引入轻量 js 文件即可。本文主要介绍对于现有的 Asp.Net Core 网站使用中间件快速记录访问日志。使用中间件的好处:在服务端进行处理,无视客户端类型(特殊信息无法获取);统一处理,不需要对每个地址重复处理等。

直奔主题,最简单的日志信息记录主要包括了访问IP,访问时间,访问地址以及来源地址,建立一个简单的模型类如下:

public class AccessLog {
    public int Id { get; set; }
    public string Ip { get; set; }
    public string Url { get; set; }
    public string Referer { get; set; }
}

数据库持久化框架主要使用 Entity Framework Core,建立简单的 DbContext ,注册服务并执行迁移得到数据库。下一步编写日志记录中间件如下:

public class AccessLogMiddleWare
{
    private readonly RequestDelegate _next;

    public AccessLogMiddleWare(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ILogger<AccessLogMiddleWare> logger, AppDbContext db)
    {
        // 切割请求地址
        var type = context.Request.Path.ToString().Split('.').Last();
        if (type == "html")
        {
            logger.LogInformation(context.Request.Path + "\t" + context.Connection.RemoteIpAddress.MapToIPv4().ToString() + "\t" + context.Request.Headers["X-Real-IP"] + "\t" + context.Request.Headers["X-Forwarded-For"] + "\t" + context.Request.Headers["Referer"]);
            //if (context.Connection.RemoteIpAddress.MapToIPv4().ToString() != "0.0.0.1") { }
            var log = new AccessLog
            {
                AccessTime = DateTime.Now,
                Ip = string.IsNullOrEmpty(context.Request.Headers["X-Real-IP"].ToString()) ? context.Connection.RemoteIpAddress.MapToIPv4().ToString() : context.Request.Headers["X-Real-IP"].ToString(),
                ForwardIp = string.IsNullOrEmpty(context.Request.Headers["X-Forwarded-For"].ToString()) ? context.Connection.RemoteIpAddress.MapToIPv4().ToString() : context.Request.Headers["X-Forwarded-For"].ToString(),
                Referer = context.Request.Headers["Referer"].ToString(),
                Url = context.Request.Path.ToString()
            };
            db.Add(log);
            await db.SaveChangesAsync();
        }
        await _next(context);
    }
}

需要注意的有几点:

  • 需要注入 DbContext 来实现保存到数据库
  • 需要注入 Configuration 来判断需要记录的类型
  • 对于使用了反向代理,需要手动判断请求头中的 X-Forawarded-ForX-Real-IP两个头来确定IP地址(尽管有 ForwardedHeadersOptions 可供使用,但对于静态文件来说,还没有到 ForwardedHeadersOptions 处理就已经返回响应了)

然后再 Srartup 里使用该中间件即可,最好把该中间件放到请求最开始的位置。

app.UseMiddleware<AccessLogMiddleWare>();
其他阅读

什么是上帝对象

上帝对象(God Object)是面向对象编程(OOP)中一种特殊现象,在面向对象编程中,我们把逻辑和数据封装成一个个对象,每个对象各司其职,最终实现我们的业务,但是如果业务复杂的情况下,可能会出现一个对象封装太多的数据或者担任了太多的职责的情况,这样的对象我们称为上帝对象。

查看原文

Nginx代理AspNetCore跨域问题

在前后端分离开发中,经常出现跨域的问题,本文是记录使用Nginx来反向代理AspNetCore应用时的跨域问题。

查看原文

解决ssh登录后闲置一段时间断开

最新新买了一台服务器,使用 ssh 登录之后发现一段时间没有输入就会自动断开,这里记录一下解决方法。

查看原文

Unity控制台打印彩色日志

在 Unity 开发过程中,我们经常需要使用 Debug.Log 来输出调试信息。但是在繁杂的控制台信息中,一些重要的信息很容易就被忽略。使用彩色日志可以大幅提升Unity开发中的调试效率。

查看原文

Fetch发送请求

fetch 是 javascript 中一个新的 api,用于访问和控制 HTTP 的请求和响应等,不再需要使用传统的 XMLHttoRequest

查看原文