我的CuteKe網站也上線一段時間了,之前也是做了通路日志,發現日志還是不利于觀察,還是把它通路記錄資料庫化了。但是這幾天卻發現在記錄URL的時候發現了一個問題。
1. 記錄URL
我們先來看看如何記錄URL與IP位址:
1.1 通路記錄Model
因為我們要把通路記錄資料化,是以我們要建立通路記錄實體類:
VistorLog
,代碼如下:
@Entity
public class VisitorLog {
private static final long serialVersionUID = 1L;
@Id // 主鍵
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增長政策
private Long id; // 使用者的唯一辨別
@NotEmpty(message = "通路位址不能為空")
@Column(nullable = false)
private String url;
@NotEmpty(message = "通路方法不能為空")
@Column(nullable = false)
private String httpMethod;
@NotEmpty(message = "IP位址不能為空")
@Column(nullable = false)
private String ip;
@NotEmpty(message = "IP位址映射的真實不能為空")
@Column(nullable = false)
private String trueAddress;
@Column(nullable = false) // 映射為字段,值不能為空
@org.hibernate.annotations.CreationTimestamp // 由資料庫自動建立時間
private Timestamp visitTime;
@NotEmpty(message = "背景通路方法不能為空")
@Column(nullable = false)
private String classMethod;
@NotEmpty(message = "通路方法參數")
@Column(nullable = false)
private String getClassMethodArgs;
protected VisitorLog(){
}
public VisitorLog(String url, String httpMethod, String ip, String trueAddress,String classMethod, String getClassMethodArgs) {
this.url = url;
this.httpMethod = httpMethod;
this.ip = ip;
this.trueAddress= trueAddress;
this.classMethod = classMethod;
this.getClassMethodArgs = getClassMethodArgs;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHttpMethod() {
return httpMethod;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getClassMethod() {
return classMethod;
}
public void setClassMethod(String classMethod) {
this.classMethod = classMethod;
}
public String getGetClassMethodArgs() {
return getClassMethodArgs;
}
public void setGetClassMethodArgs(String getClassMethodArgs) {
this.getClassMethodArgs = getClassMethodArgs;
}
}
1.2 利用Spring AOP
在gradle裡添加
spring-boot-starter-aop
依賴以後,我們可以這樣設計:
- 切入點:每個
的每個方法即各個請求方法Controller
@Pointcut("execution(public * com.cuteke.spring.boot.blog.controlller.*.*(..))")
public void log() {
};
- 通知:在這裡我選擇的是
,你也可以選擇其他通知前置通知
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
....
}
- 擷取HttpServletRequest:我們通過Request上下文來擷取
HttpServertRequest
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
- 擷取各個屬性:擷取到
就可以通過調用其方法就可以擷取到HttpServertRequest
的各個屬性了:VisitLog
String url=new String(request.getRequestURL());
String method=request.getMethod();
String ip=IpUtil.getClinetIpByReq(request);
String class_method=joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
String args= Arrays.toString(joinPoint.getArgs());
logger.info("url={} method={} ip={} class_method={} args={}", url, method
, ip, class_method
, joinPoint.getArgs());
VisitorLog visitorLog=new VisitorLog(url,method,ip,IpUtil.getAddressByIP(ip),class_method,args);
vistorLogService.saveVistorLog(visitorLog);
是處理ip的工具類,核心思想是通過
IpUtil
方法和過濾掉代理ip來實作的,我們會在其餘章節裡面提到,百度也能很簡單的找到
getRemoteAddr()
2. URL不符合
網站上線了幾個星期,我在資料找到了很奇怪的記錄,如下圖1所示:
圖1. 資料庫中行URL不符合
其中怪異的url我都用紅線劃出來了,而且發現了沒,這些搞事的url都是國外的,國外還是喜歡搞事情呀!
2.1 是否使用代理?
代理可以分為兩種:
- 正向代理:用戶端要配置代理伺服器,由代理伺服器代替通路你,是以說URL一般并不會改變
-
反向代理:用戶端不知道代理的存在,通路URL的網址時,會經過反向代理伺服器,由反向代理伺服器轉向對應的伺服器上通路,一般用于
負載均衡,URL一般也不會改變
其實使用代理的情況下是可以出現我這種情況的,因為伺服器的存在,修改URL或者其他操作是使用者不知道的,我們知道URL是用來解析ip位址,像國外這種情況隻要能确定我的伺服器IP位址,不管URL是不是我的網站URL,都可以通路我的網站。
2.2 HOST實踐
前面講到隻要解析我的伺服器IP位址不管URL是否正确都可以,我們就在本機實踐一下,我們知道在C:\Windows\System32\drivers\etc有一個HOST檔案,我們隻要改變URL對應的IP即可完成解析。代碼如下:
# localhost name resolution is handled within DNS itself.
127.0.0.1 localhost
# ::1 localhost
127.0.0.1 www.cuteke.cn
在這裡我把自己的網站域名解析成本機位址,在本機我也開啟我的網站,不過裡面内容不一樣,在浏覽器輸入
www.cuteke.cn
,發現頁面如下圖所示:
圖1. 本地通路CuteKe網站
這頁面是本機伺服器展示展示的頁面,因為本機的置頂文章和公網上置頂的文章不一樣。同時我們看一下本地資料庫的通路記錄:
圖2. 本地資料庫通路記錄
最後兩行我們可以發現URL并不是
localhost
而是
www.cuteke.cn
,也是驗證了我們的思想。
修改HOSTS檔案後如果通路的URL還是解析成原來的位址,那麼記得清楚一下系統DNS和浏覽器DNS緩存
修改HOSTS檔案隻是其中一種可能,還有一種極大的可能是Http Host頭攻擊,我們在下一章會講述其原理和具體防禦措施
參考資料
[1] Spring Boot進階之Web進階
[2] 正向代理與反向代理【總結】