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

发布时间: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>();
其他阅读

Angular使用路由复用实现单页多窗(Tab页形式)

我们在开发后台管理系统时,一个很重要的需求就是多窗口编辑,来回切换使用。一种思路是使用iframe来记录多个多页面展示,本文通过Angular路由复用来实现这一需求。

查看原文

使用正则表达式来判断邮箱

在开发中,很多地方都需要用户输入邮箱,用户注册,登录需要邮箱,订阅消息需要邮箱,为了防止被恶意使用,一般都会使用正则表达式来判断输入是否符合邮箱规范

查看原文

未来设计趋势-Bento Layout/便当布局

前几天找网站设计的灵感的时候,发现一个介绍2024年网站设计趋势的视频,里面介绍了一个叫 Bento Layout 的趋势,今天就给大家分享一下什么是 Bento Layout,中文称为“便当布局”。

查看原文

IIS 设置跨域问题

之前说过nginx设置跨域,今天记录以下IIS设置跨域

查看原文

自驾环游抚仙湖

抚仙湖作为云南第三大湖,以前只去过北边几个开发比较好的区域,周末闲来无事,准备自驾完整地环湖一圈,从呈贡出发,沿着国道开到澄江,然后环湖一圈,经过江川后再到澄江,吃完饭后回到呈贡。

查看原文