2015-05-03 24 views
4

當訪問者提交表單時,我想聯合輸入他的IP地址。如何獲取ring-clojure中的客戶端IP地址?

(POST "/form" {params :params} (assoc params :ip-address the-ip) 

如何做到這一點?

這樣的思想:

(POST "/form" {params :params 
       client-ip :remote-addr} 
     (->> params keywordize-keys (merge {:ip-address client-ip}) str)) 

但這返回{... :ip-address "0:0:0:0:0:0:0:1"}

+0

這是在ipv6中的'localhost'。你的請求來自哪裏? – cfrick

+0

@cfrick localhost。是啊。我無法在prod中測試這個,所以不確定':remote-addr'是否構成你的答案,我想這是對的。 – leontalbot

+0

順便說一句,剛發現我不需要使用一個關鍵字密鑰函數。只需要'wrap-keyword-params'。 https://stackoverflow.com/questions/26151801/ring-middleware-and-compojure-params-with-keywords – leontalbot

回答

4

亞瑟Ulfeldt對比爾的答案評論,我想我們可以這樣寫:

(defn get-client-ip [req] 
    (if-let [ips (get-in req [:headers "x-forwarded-for"])] 
    (-> ips (clojure.string/split #",") first) 
    (:remote-addr req))) 
+0

//,這會返回一個IPv6地址嗎? –

+0

@NathanBasanese如果我正確地得到你的問題,我的答案是我沒有測試一個IPV6源。我不知道它是否會正確地返回這樣一個字符串。 – leontalbot

0

我敢肯定,你可以從環請求對象信息。看看ring.middleware.dump(handle-dump)包。如果你設置了這個和一個簡單的路徑來使用它,你會得到一個很好的網頁,顯示一個響鈴請求對象中提供的所有可用值。很確定這包括客戶端IP地址。由於這些信息是從http頭獲得的,所以它可能比手動將它放入請求參數更可靠 - 使用表單或json將其放入請求參數中可能意味着僞造更容易。此外,如果它已經作爲請求對象的一部分已經可用,意味着你需要做的更少。

4

獲取:remote-addr從請求對象通常是去除非你坐在後面的負載平衡器的正確方法。在這種情況下,您的負載平衡可能會添加一個頭x-forwarded-for的要求。這會使這樣的事情合適。

(or (get-in request [:headers "x-forwarded-for"]) (:remote-addr request)) 
+4

這對於自己在代理之後的客戶端來說會失敗,因爲x-forwarded-for將是一個逗號分隔的IP列表,如「2.2.2.2.5.5」。 5.5「與你想要的實際地址作爲*之前的所有內容*,並記住它們也可以是IPv6地址,即使你的服務位於IPv4 –