2010-08-31 82 views
3

我最近在PHP中編寫了一個套接字服務器,它將處理Android手機應用程序和我的PHP網絡服務器之間的通信。由於Android本身不支持推式通知,因此我們將使用我們的網絡服務器作爲中間件層來處理我們的「推送」。PHP Socket服務器(用於Android推送通知) - 安全/身份驗證問題

套接字服務器是穩定的,運行良好,似乎很好地縮放。雖然我最終希望用C重寫這個,但我現在沒有必要的技能來做這件事,所以我將至少在PHP中停留至少一段時間。截至目前,我們的Android模擬器能夠通過服務器進行通信,獲得推送等,以便覆蓋部分內容。

我擔心的是,現在任何人都可以打開一個套接字到我的服務器,並且會得到一個客戶端連接。雖然我們不會傳遞敏感數據,但我不想讓任何人連接並接收廣播信息,吞併我的資源,並阻塞我的服務器。

問題是,如何保護這樣的服務器?假設我在端口25,000上運行 - 是否可以在該端口上設置某種SSL層,並希望像Android這樣的設備能夠通過該端口進行通信,而無需使用任何特殊協議或跳過循環?

我曾考慮要求連接客戶端在給予客戶端連接之前,根據我們的用戶數據庫對其用戶進行身份驗證,但這需要通過網絡以純文本形式傳遞憑證,而我不打算這麼做。

對此的任何建議都會非常有幫助 - 我對PHP的直接TCP通信頗爲陌生,覺得我可能會錯過簡單的允許在此級別進行身份驗證的內容。

附加信息:如果我能夠安全地獲取有效的用戶名和密碼,我將使用MySQL來驗證用戶,然後根據查詢結果接受/拒絕他們的連接。

在此先感謝..

回答

1

首先,我希望你實現你的PHP套接字服務器的方式,它允許多個客戶端同時連接。這並不像在PHP中缺少線程那麼簡單,但當然是這樣。

現在,如果您已經實現了套接字服務器,添加TLS支持很容易。只需運行stunnel並讓您的PHP套接字服務器只接受本地接口上的請求。

+0

哦,是的,我目前正在處理多個客戶,沒有任何問題,所以這部分被覆蓋。我會看看stunnel,看看看起來像什麼。我不確定我如何僅使用本地接口進行連接,除非stunnel以某種方式處理到服務器的入站連接 - 更多的研究將回答它看起來像。 – Shane 2010-08-31 16:21:39

+0

@angry是的,這就是stunnel所做的。它在解密入口流量並加密出站流量後中繼入站流量。 – Artefacto 2010-08-31 16:25:50

1

我不認爲SSL真的會解決您的問題。最好使用SSL,您可以爲每個客戶端提供一個客戶端證書並在服務器上進行客戶端證書驗證。但是,您需要管理大量的證書。或者給每個人提供相同的客戶證書(不是一個好主意)。

您必須使用其憑證對客戶端進行身份驗證。你是對的,你不想通過網絡以純文本的形式發送證書,但有簡單的選擇。看看例如HTTP摘要認證(http://en.wikipedia.org/wiki/Digest_access_authentication)或xAuth(http://dev.twitter.com/pages/xauth)。您不必通過HTTP實現這些技術;你也可以在接受連接後通過一個簡單的tcp套接字發送挑戰(領域)。客戶端應該在短時間內發送有效的響應,或者服務器放棄連接。

順便說一下,你認爲HTTP流?請參閱http://ajaxpatterns.org/HTTP_Streaming 這可能會讓您的生活變得更加輕鬆,因爲您可以依賴一些其他服務(例如Apache)爲您辛苦工作,並且您可以專注於應用程序的業務價值。

+0

這是一個有趣的想法,但我不確定這將適用於我們的Android設置。我使用套接字(而不是輪詢數據)的原因是爲了延長移動設備的電池壽命。我可能是錯的,但我預計長期存在的HTTP套接字可能會在頭文件中產生更多開銷,並可能會消耗太多的資源。我會記住這一點,但如果我無法弄清楚如何讓這一切都鎖定下來..謝謝! – Shane 2010-08-31 16:27:36

+0

請求/響應頭只發送一次,然後服務器和客戶端只是保持連接打開很長時間。如果客戶想發送一些他可以放棄連接的東西,發送一個新的請求(包含有效載荷)並且繼續再次持有長期連接。只要沒有數據來回傳遞,連接就不會做任何事情。你可能想讓服務器不時地發送一個「NOOP」,所以代理不會中斷連接 – schuilr 2010-08-31 17:13:29

+0

另外:端口25000被阻止離開我的辦公室。通過使用HTTP,可以使用代理和防火牆在此端口上更友好。 – schuilr 2010-08-31 17:14:18

0

你可能要考慮: 雲端至設備通訊:http://code.google.com/android/c2dm/index.html

唯一的缺點是,它僅是Android支持> = 2.2

+0

謝謝!儘管如此,您確實提到了使用該服務的確切問題。很長一段時間我們會支持<2.2的設備(不幸的是),所以我必須有一些東西可以在每個人身上得到補償。 – Shane 2010-08-31 17:05:14

0

不知道爲什麼你們沒有使用過的一些用於java的架子消息庫/服務器,然後創建一個連接到消息代理並處理所有初始認證的android服務。 服務只是坐在那裏等待任何傳入的消息。

(我敢肯定是監聽網絡數據不加電的收音機,只有當數據實際上有無線電的權力了。我懷疑這是C2DM是如何工作的。) 這是因爲你只是在等待數據,所以更好的是輪詢。你並不是經常發送請求數據的數據包。但是你已經知道了。

我這樣做了(我使用了rabbitmq-java庫和rabbitmq消息隊列服務器),並且立即爲我的應用推送了樣式通知。即使使用Android 1.5設備。

關於安全:

你也可以實現自己的安全,而且不必再發送明文密碼。在通過網絡傳遞之前,使用類似MD5的密碼來簡單加密密碼。
然後將加密的密碼與您擁有的加密密碼進行比較。 這樣,只有加密的密碼纔會通過網絡。

+0

MD5對密碼進行哈希處理並不能安全地以明文形式傳遞它。特別是因爲像http://md5.rednoize.com/這樣的網站已經映射哈希,並且可以很容易地解密常見密碼。另外,我們並未在服務器上運行Java,因此需要大量的開銷才能運行現成的應用程序進行身份驗證 - 而且我們的身份驗證必須針對我們的應用程序進行自定義,因此不確定該效果如何。雖然謝謝! – Shane 2010-09-02 15:27:20

+0

您可以使用比MD5更強的東西,並將連接包裝在SSL中。 理想情況下,您應該:SSL + Crypted(密碼) - >服務器 此外,我的意思是建議您使用包含內置身份驗證的現成*消息*服務器。它可以取代你完全建立的php套接字服務器。 (即您將郵件從您的服務器應用程序發佈到mq服務器,所連接的客戶端會收到他們打算接收的任何郵件。) 您可以在這些mq服務器上使用多種語言。 其中一些MQ服務器支持SSL和各種身份驗證方法。 無論如何,祝你好運 – 2010-09-02 15:58:55