今天服務裏的微信公衆號支付業務忽然不能用了,報錯爲網絡環境未能經過安全驗證,請稍後再試。檢查後端日誌,沒有任何問題,看來是成功建立支付訂單,可是調起支付時出現了問題。上網查了一下,這個報錯的直接緣由是傳入的客戶端ip與調起支付的ip不符。可是印象中我在代碼中獲取的是X-Forwarded-For,就是請求來源的客戶端IP,就查看日誌發現傳給微信的ip爲172.17.0.1,也就是宿主機ip,這是才恍然大悟,在升級線上環境時咱們將全部服務放進了docker,而且在docker裏裝了nginx來分發請求給對應的服務,也就是說咱們是兩級nginx代理,咱們的服務是無法拿到最外層客戶端ip的。只好改進nginx將每級代理的ip都記錄起來,而不是直接覆蓋。nginx
改進方法:docker
對第一級nginx代理後端
location ~ ^/test {
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}安全
第一級nginx代理不須要改動,直接將原始客戶端ip記錄到X-Forwarded-For便可微信
對於第二級,以及以後可能存在的更多級代理網絡
location ~ ^/test {
proxy_pass http://127.0.0.1:12000;
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}spa
這樣就將新一級代理的ip接到X-Forwarded-For的尾部,並用逗號分割。也就是說X-Forwarded-For是一個逗號拼接的ip字符串,想拿到原始ip只須要按逗號分割,取第一位ip便可。代理
Golang業務中讀取原始客戶端ip代碼日誌
real_ip := r.Header.Get("X-Forwarded-For") ip_list := strings.Split(real_ip, ",") if len(ip_list) > 1 { real_ip = ip_list[0] }
就是這麼簡單啦,但願對你們有所幫助~blog