简体   繁体   English

PHP套接字服务器(用于Android推送通知) - 安全/身份验证问题

[英]PHP Socket Server (for Android Push Notifications) - Security / Authentication Issue

I have recently written a socket server in PHP that will be handling communication between an Android phone application and my PHP webserver. 我最近在PHP中编写了一个套接字服务器,它将处理Android手机应用程序和我的PHP网络服务器之间的通信。 Due to the fact that Android doesn't natively support push style notifications we are going to be using our webserver as the middleware layer to handle our 'pushes'. 由于Android本身不支持推送式通知,我们将使用我们的Web服务器作为中间件层来处理我们的“推送”。

The socket server is stable, runs well, and seems to scale nicely. 套接字服务器稳定,运行良好,似乎可以很好地扩展。 While I would eventually like to re-write this in CI don't have the skill necessary to do that right now so I am going to be staying in PHP for at least a short while. 虽然我最终想在CI中重新编写它,但是现在没有必要的技能,所以我将至少在PHP中停留一段时间。 As of this moment our Android emulator is able to communicate through the server, get pushes, etc. so that part is all covered. 到目前为止,我们的Android模拟器能够通过服务器进行通信,推送等等,以便部分全部覆盖。

My concern is that, right now, anyone can open a socket to my server and will be given a client connection. 我担心的是,现在,任何人都可以打开我的服务器的套接字,并将获得客户端连接。 While we won't be passing sensitive data back and forth I don't want to allow just anyone to connect over and receive broadcast information, eat up my resources, and clog my server in general. 虽然我们不会来回传递敏感数据,但我不想让任何人连接并接收广播信息,耗尽我的资源,并阻塞我的服务器。

The question is, how do I secure a server like this? 问题是,如何保护这样的服务器? Let's assume that I am running on port 25,000--can I set up some sort of SSL layer on that port and expect devices like the Android to be able to communicate over that port without any special protocols or jumping through hoops? 让我们假设我在端口25,000上运行 - 我可以在该端口上设置某种SSL层,并期望像Android这样的设备能够通过该端口进行通信,而无需任何特殊协议或跳过箍?

I have considered asking the connecting clients to authenticate their user against our user database before being given a client connection, but that would require the passing of credentials in plain text over the network which I am NOT about to do. 我已经考虑过要求连接客户端在给定客户端连接之前根据我们的用户数据库对用户进行身份验证,但是这需要通过网络以纯文本形式传递凭据,我不打算这样做。

Any suggestions on this would be very helpful--I am rather new to straight TCP communication from PHP and feel like I might just be missing something simple that allows for authentication on this level. 任何有关这方面的建议都会非常有用 - 我对PHP的直接TCP通信很新,并且觉得我可能只是缺少一些允许在此级别进行身份验证的简单方法。

Additional information: If I am able to get a valid username and password securely I would be using MySQL to validate the user and then accept/reject their connection based on the results of the query. 附加信息:如果我能够安全地获得有效的用户名和密码,我将使用MySQL来验证用户,然后根据查询结果接受/拒绝他们的连接。

Thanks in advance.. 提前致谢..

First, I hope you've implemented your PHP socket server in a fashion that allows more than one client to be connected at the same time. 首先,我希望您以一种允许同时连接多个客户端的方式实现您的PHP套接字服务器。 This is not as trivial as it should be given the absence of threads in PHP, but it's certainly. 这不是因为在PHP中缺少线程应该是微不足道的,但它肯定是。

Now, if you already have a socket server implemented, adding TLS support is easy. 现在,如果您已经实现了套接字服务器,那么添加TLS支持很容易。 Just run stunnel and have your PHP socket server only accept requests on the local interface. 只需运行stunnel并让您的PHP套接字服务器只接受本地接口上的请求。

I don't think SSL is really going to solve your problem. 我不认为SSL真的会解决你的问题。 At best with SSL you can provide each client with a client certificate and do client certificate validation on the server. 最好使用SSL,您可以为每个客户端提供客户端证书,并在服务器上进行客户端证书验证。 But you'll need to manage tons of certificates then. 但是你需要管理大量的证书。 Or give everyone the same client certificate (not a good idea). 或者给每个人相同的客户证书(不是一个好主意)。

You'll have to authenticate the client using his credentials. 您必须使用其凭据对客户端进行身份验证。 You are right that you don't want to send the credentials in plain text over the network, but there are simple alternatives. 你是对的,你不想通过网络以纯文本形式发送凭证,但有一些简单的替代方案。 Take a look at eg HTTP Digest Authentication ( http://en.wikipedia.org/wiki/Digest_access_authentication ) or xAuth ( http://dev.twitter.com/pages/xauth ). 请查看HTTP摘要式身份验证( http://en.wikipedia.org/wiki/Digest_access_authentication )或xAuth( http://dev.twitter.com/pages/xauth )。 You don't have to implement these techniques over HTTP; 您不必通过HTTP实现这些技术; you can just as well send a challenge (a realm) over a simple tcp socket after you have accepted the connection. 您可以在接受连接后通过简单的tcp套接字发送挑战(领域)。 The client should then send a valid response within a short timeframe or the server aborts the connection. 然后,客户端应在短时间内发送有效响应,否则服务器将中止连接。

By the way, did you consider HTTP streaming? 顺便问一下,您是否考虑过HTTP流媒体? See http://ajaxpatterns.org/HTTP_Streaming It would probably make your life a lot easier as you can rely upon some other service (eg Apache) doing the hard work for you, and you can focus on the business value of your application. 请参阅http://ajaxpatterns.org/HTTP_Streaming这可能会让您的生活变得更轻松,因为您可以依赖其他服务(例如Apache)为您做出艰苦的工作,并且您可以专注于应用程序的业务价值。

you might want to consider: Cloud to Device Messaging : http://code.google.com/android/c2dm/index.html 您可能需要考虑:云到设备消息: http//code.google.com/android/c2dm/index.html

The only drawback is that it is only supported by android >=2.2 唯一的缺点是它只支持android> = 2.2

Not sure why you guys didn't use some off the shelf messaging library/server for java, then create an android service that connects to the message broker and handles all initial authentication. 不知道为什么你们没有使用一些现成的消息库/服务器为java,然后创建一个连接到消息代理并处理所有初始身份验证的android服务。 The service would simply sit there and wait for any incoming messages. 该服务只是坐在那里等待任何传入的消息。

(I'm pretty sure that listening for network data doesn't power up the radio, only when the data is actually there that the radio powers up. I suspect this is how C2DM works.) This is better then polling because you're only waiting for data. (我很确定收听网络数据不会打开无线电,只有当数据确实存在时,无线电上电。我怀疑这是C2DM的工作原理。)这比轮询更好,因为你是只等待数据。 You're not constantly sending packets requesting data. 您不是经常发送请求数据的数据包。 But you knew that already. 但是你已经知道了。

I did this, (I used the rabbitmq-java library and the rabbitmq message queue server) and had push style notification for my app in no-time. 我做了这个,(我使用了rabbitmq-java库和rabbitmq消息队列服务器),并且在任何时候都为我的应用程序提供了样式通知。 Even with Android 1.5 devices. 即使使用Android 1.5设备。

About security: 关于安全:

You could also implement your own security but without having to send plain-text passwords. 您也可以实现自己的安全性,但无需发送纯文本密码。 Simply encrypt the passwords using something like MD5 before passing it through the network. 只需在通过网络之前使用MD5等密码对密码进行加密。
Then compare the encrypted password with the encrypted password you have on file. 然后将加密密码与您存档的加密密码进行比较。 This way, only encrypted passwords will go through the network. 这样,只有加密的密码才能通过网络。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM