2010-08-31 15 views
3

J'ai récemment écrit un serveur socket en PHP qui va gérer la communication entre une application de téléphone Android et mon serveur web PHP. Étant donné qu'Android ne prend pas en charge de manière native les notifications de style push, nous allons utiliser notre serveur Web comme couche de middleware pour gérer nos «push».PHP Socket Server (pour les notifications Push Android) - Sécurité/Authentification Problème

Le serveur de socket est stable, fonctionne bien et semble évoluer correctement. Bien que je voudrais finalement réécrire cela en C je n'ai pas les compétences nécessaires pour le faire maintenant, je vais rester en PHP pendant au moins un court moment. À partir de ce moment, notre émulateur Android est capable de communiquer via le serveur, d'obtenir des poussées, etc. afin que toute la partie soit couverte. Ce qui m'inquiète, c'est que tout le monde peut ouvrir une socket sur mon serveur et recevoir une connexion client. Même si nous ne transmettons pas de données sensibles, je ne veux pas permettre à quiconque de se connecter et de recevoir des informations diffusées, de gaspiller mes ressources et d'encombrer mon serveur en général.

La question est, comment puis-je sécuriser un serveur comme celui-ci? Supposons que je cours sur le port 25 000. Puis-je installer une sorte de couche SSL sur ce port et attendre des appareils comme l'Android pour pouvoir communiquer sur ce port sans protocoles spéciaux ou sauter par des cerceaux? J'ai envisagé de demander aux clients qui se connectent d'authentifier leur utilisateur par rapport à notre base de données utilisateur avant de recevoir une connexion client, mais cela nécessiterait le transfert d'informations en texte brut sur le réseau, ce que je ne suis pas sur le point de faire. Toutes les suggestions sur ce serait très utile - je suis plutôt nouveau à la communication TCP directe de PHP et me sens comme je pourrais juste manquer quelque chose de simple qui permet l'authentification à ce niveau. Informations complémentaires: Si je peux obtenir un nom d'utilisateur et un mot de passe valides, j'utiliserais MySQL pour valider l'utilisateur, puis accepter/refuser sa connexion en fonction des résultats de la requête.

Merci à l'avance ..

Répondre

1

d'abord, j'espère que vous avez mis votre serveur socket PHP d'une manière qui permet à plus d'un client à être connecté en même temps. Ce n'est pas aussi trivial que cela devrait être compte tenu de l'absence de threads en PHP, mais c'est certainement le cas. Maintenant, si vous avez déjà un serveur socket implémenté, l'ajout de la prise en charge TLS est facile. Exécutez simplement stunnel et demandez à votre serveur de socket PHP d'accepter uniquement les demandes sur l'interface locale.

+0

Oh oui, je gère plusieurs clients sans aucun problème pour le moment, donc cette partie est couverte. Je vais jeter un oeil à Stunnel et voir à quoi ça ressemble. Je ne suis pas sûr comment je peux utiliser seulement l'interface locale pour des connexions SAUF si stunnel manipule d'une manière ou d'une autre les connexions entrantes au serveur - plus de recherche répondra que cela ressemble. – Shane

+0

@angry Oui, c'est ce que fait stunnel. Il relaie le trafic entrant après le décryptage et crypte le trafic sortant. – Artefacto

1

Je ne pense pas que SSL va vraiment résoudre votre problème. Au mieux avec SSL, vous pouvez fournir à chaque client un certificat client et effectuer la validation du certificat client sur le serveur. Mais vous devrez gérer des tonnes de certificats alors. Ou donner à tout le monde le même certificat de client (pas une bonne idée).

Vous devrez authentifier le client en utilisant ses informations d'identification. Vous avez raison de ne pas envoyer les informations d'identification en texte brut sur le réseau, mais il existe des alternatives simples. Jetez un coup d'œil par exemple Authentification HTTP Digest (http://en.wikipedia.org/wiki/Digest_access_authentication) ou xAuth (http://dev.twitter.com/pages/xauth). Vous n'avez pas à implémenter ces techniques sur HTTP; vous pouvez tout aussi bien envoyer un challenge (un domaine) sur une simple socket tcp après avoir accepté la connexion. Le client doit alors envoyer une réponse valide dans un court délai ou le serveur annule la connexion. En passant, avez-vous considéré le streaming HTTP?Voir http://ajaxpatterns.org/HTTP_Streaming Cela vous facilitera probablement la vie, car vous pouvez compter sur un autre service (par exemple, Apache) qui travaille dur pour vous et vous pouvez vous concentrer sur la valeur commerciale de votre application.

+0

C'est une idée intéressante, mais je ne suis pas sûr que cela fonctionne pour notre configuration Android. La raison pour laquelle je suis allé avec des sockets (au lieu de simplement interroger des données) est d'économiser la batterie sur l'appareil mobile. Je peux me tromper, mais je prévois qu'une socket HTTP de longue durée restant ouverte pourrait créer plus de frais généraux avec des en-têtes et pourrait consommer trop de ressources. Je vais garder cela à l'esprit si au cas où je ne peux pas comprendre comment faire tout cela verrouillé .. Merci! – Shane

+0

Les en-têtes de demande/réponse sont envoyés une seule fois, puis le serveur et le client gardent cette connexion ouverte très longtemps. Si le client veut envoyer quelque chose, il peut annuler la connexion, envoyer une nouvelle requête (avec la charge utile) et continuer à maintenir une connexion de longue durée. Tant qu'il n'y a pas de données qui vont et viennent, la connexion ne fait rien. Vous pouvez laisser le serveur envoyer un "NOOP" de temps en temps, donc les proxies ne tuent pas la connexion – schuilr

+0

En outre: le port 25000 est bloqué de mon bureau. Passer par HTTP avec ceci permet l'utilisation de proxies et les pare-feu sont beaucoup plus amicaux sur ce port. – schuilr

0

vous pouvez envisager: Cloud Messaging Device: http://code.google.com/android/c2dm/index.html

Le seul inconvénient est qu'il est pris en charge par Android> = 2.2

+0

Merci! Vous avez mentionné mon problème avec l'utilisation de ce service. Nous allons supporter des appareils <2.2 pendant longtemps (malheureusement) donc je dois avoir quelque chose qui marchera pour tout le monde. – Shane

0

Je ne sais pas pourquoi les gars ne sommes pas allés un peu au large la bibliothèque/serveur de messagerie sur étagère pour Java, puis créez un service Android qui se connecte au courtier de messages et gère toutes les authentifications initiales. Le service resterait simplement là et attendrait les messages entrants.

(je suis assez sûr que l'écoute des données de réseau ne met pas sous tension la radio, que lorsque les données sont en fait là que les pouvoirs de la radio vers le haut. Je soupçonne que ce comment fonctionne C2DM.) C'est mieux que l'interrogation car vous n'attendez que des données. Vous n'envoyez pas constamment de paquets demandant des données. Mais tu le savais déjà. J'ai fait ceci, (j'ai utilisé la bibliothèque de rabbitmq-java et le serveur de file d'attente de message de rabbitmq) et avait la notification de style de poussée pour mon application en un rien de temps. Même avec les appareils Android 1.5.

A propos de la sécurité:

Vous pouvez également mettre en œuvre votre propre sécurité, mais sans avoir à envoyer des mots de passe en texte clair. Il suffit de crypter les mots de passe en utilisant quelque chose comme MD5 avant de le passer à travers le réseau.
Puis comparez le mot de passe crypté avec le mot de passe crypté que vous avez dans le fichier. De cette façon, seuls les mots de passe chiffrés passeront par le réseau.

+0

MD5 hacher un mot de passe ne permet pas de le transmettre en clair. D'autant plus que des sites comme http://md5.rednoize.com/) mappaient les hachages et facilitaient le décryptage des mots de passe communs.De plus, nous n'exécutons pas Java sur nos serveurs, ce qui nécessiterait beaucoup de frais généraux pour exécuter une application standard afin de s'authentifier. De plus, notre authentification devrait être personnalisée pour notre application, donc nous ne savons pas si cela fonctionnerait correctement. Merci quand même! – Shane

+0

Vous pouvez utiliser quelque chose de plus fort que MD5 et encapsuler la connexion dans SSL. Idéalement, vous devriez: SSL + Crypted (mot de passe) -> Serveur Aussi, je voulais vous suggérer d'utiliser un serveur * de messagerie * standard * qui inclut l'authentification intégrée. Il pourrait remplacer le serveur socket PHP que vous avez construit complètement. (Par exemple, si vous publiez des messages de votre application serveur sur le serveur mq, les clients connectés reçoivent les messages qu'ils sont censés recevoir.) Vous pouvez utiliser plusieurs langues avec ces serveurs mq. Certains de ces serveurs MQ prennent en charge SSL et diverses méthodes d'authentification. En tout cas, bonne chance –