需求:記錄用戶操作記錄,類似如下表格的這樣
PS: 注意無論你的服務是Http訪問還是Https 訪問的都是可以的,我們服務之前是客戶只給開放了一個端口,但是既要支持https又要支持http協議,nginx 是可以通過stream 模塊配置雙協議支持,但是stream塊是四層協議,無法獲取到真實的用戶IP地址,后來把http協議關閉了,才能繼續獲取IP地址,如果有類似的情況可以檢查是不是也有stream塊配置。
用戶名 | IP地址 | 瀏覽器 | 操作 | 模塊 |
---|---|---|---|---|
XX | ip | Chrome | 瀏覽 | 【范洪月】 瀏覽xx功能 |
XX | ip | Chrome | 瀏覽 | 【范洪月】 瀏覽xx功能 |
我們是從外網穿透到內網的,真實鏈路如下
外網Nginx
我在本地用Vmware模仿一下正式環境
開啟Nginx訪問日志 &格式化日志輸出
把這兩段打開查看 /logs/access.log
日志參數 | 參數含義 |
---|---|
$remote_addr | 遠程訪問IP地址 |
$remote_user | 遠程訪問用戶 |
$time_local | 日志時間(03/Nov/2020:14:38:06 +0800) |
$time_iso8601 | 日志時間(2020-11-03T14:42:53+08:00) |
$request | 請求的URI和HTTP協議 |
$http_host | 客戶端請求中的Host請求頭字段的值 |
$status | HTTP請求狀態 |
$upstream_status | upstream狀態 |
$body_bytes_sent | 發送給客戶端文件內容大小 |
$http_referer | url跳轉來源 |
$http_user_agent | 用戶終端瀏覽器等信息 |
$ssl_protocol | SSL協議版本 |
$ssl_cipher | 交換數據中的算法 |
$request_time | 整個請求的總時間 |
$upstream_response_time | 請求過程中,upstream響應時間 |
$upstream_response_time | 請求過程中,upstream響應時間 |
$http_x_forwarded_for | 在經過代理或負載均衡器時會逐級添加上每一級的代理服務器的IP地址 |
修改日志時間格式
雖然**$time_iso8601** 格式也能看時間,但是如果能修改成 yyyy-MM-dd HH:mm:ss 這樣就更合理了,在網上百度以后,
https://blog.csdn.net/shipfei_csdn/article/details/108440538
這個寫的很詳細。
在Server 塊中定義好時間變量
# 自定義時間變量if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})") {set $year $1;set $month $2;set $day $3;set $hour $4;set $minutes $5;set $seconds $6;}
修改日志時間格式
log_format main '$year$month$day $hour:$minutes:$seconds ' '[$status] ' '【$http_x_forwarded_for $remote_addr $http_host】''[$request_uri] ' ;
增加真實IP追蹤
Nginx01配置
location /api/{proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.10.208/api/;}
Nginx02配置
location /api/ {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.10.211;}
Nginx03配置
location /api/ {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.10.43:7001/gateway/serviceA/test;}
Nginx03 查看日志運行結果如下
20240229 01:22:45 [200] 【192.168.10.43, 192.168.10.207 192.168.10.208 192.168.10.207】[/gateway/serviceA/test]
也就是x_forwarded_for 中第一個就是訪問我們客戶端訪問的IP地址了。
Java代碼獲取IP地址代碼
- Hutool 中的 UserAgentUtil 可以獲取瀏覽器的類型的
- 獲取x-forwarded-for 中的第一個即為原始的訪問IP地址,無論經過多少層代理
public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if (StringUtils.equals("127.0.0.1", ipAddress) || StringUtils.equals("0:0:0:0:0:0:0:1", ipAddress)) {InetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException var4) {log.error(" 獲取客戶端IP異常 ", var4);}ipAddress = inet.getHostAddress();}}if (ipAddress != null && ipAddress.length() > 15 && ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}return ipAddress;}