問題的拋出
今天有合作商戶反映,批付交易完成后,在我方服務器以“服務器點對點通信”的方式通知請求對方服務器時,對方攔截了請求。並貼了一張截圖。
從截圖可以看出來,對方攔截了我們的user-agent(Apache-HttpClient)。
什么是User-Agent?
通常我們用瀏覽器訪問一個網頁,當我們向服務器發送請求時,瀏覽器會將一些頭信息附加上,然后發給服務器,其中就包括User-Agent。一些網站的網頁,為了防止爬蟲或惡意訪問,會首先判斷請求頭的User-Agent,如果不是瀏覽器請求,則會直接拒絕請求。(https://blog.csdn.net/frankcheng5143/article/details/54096098里也提到,直接用HttpClient發起請求csdn時,會收到403 Forbidden)
不同版本的谷歌瀏覽器的User-Agent:
Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36
Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)
解決問題
通過分析httputil代碼,發現我方並未設置請求頭的user-agent屬性。 原來,經模擬點對點請求的測試證明,如果不設置的話,它的值默認是:Apache-HttpClient。
技術支持同事為了照顧合作商戶的感受,建議我方改一下。那么,自然是加上user-agent來模擬正常的瀏覽器請求客戶服務器就可以了。
當然,單從技術角度來看,另一個同事的給的建議也許更好:因為這是個服務器點對點通信,所以若要從安全方面控制,應該通過諸如ip白名單的方式,而不是通過User-Agent判斷是不是瀏覽器請求。
httputil代碼(user-agent不區分大小寫):
String userAgent = "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36"; HttpGet httpGet = new HttpGet(url); httpGet.setHeader("User-Agent",userAgent); response = httpclient.execute(httpGet);
CloseableHttpClient httpClient = getHttpClient(); 。。。。。 HttpPost post = new HttpPost(url); post.setHeader("user-agent","Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); CloseableHttpResponse httpResponse = httpClient.execute(post);
URL urls = new URL(url); HttpURLConnection uc = (HttpURLConnection) urls.openConnection(); uc.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); 。。。 uc.setRequestMethod("POST"); 。。。