Over werken met webservices

Dit artikel is een verkenning van webservice-protocollen, gemeenschappelijke indelingen voor gegevensuitwisseling en praktische tips. Als u geïnteresseerd bent in het maken van performante mobiele applicaties die verbinding maken met internet, lees dan verder!


Een protocol en gegevensformaat kiezen

Het selecteren van een goed protocol en gegevensuitwisselingsformaat om gegevens door te sturen tussen uw mobiele app en het net is een van de belangrijkste beslissingen die moeten worden genomen tijdens het ontwikkelingsproces. De meest voorkomende en meest gebruikte protocollen zijn REST, XML-RPC en SOAP.

Al deze protocollen transporteren gegevens via het HTTP-protocol. De XML-RPC- en SOAP-protocollen zijn gebaseerd op XML, terwijl REST-services kunnen vertrouwen op verschillende gegevensindelingen, waarvan de twee meest voorkomende XML en JSON zijn. Met name SOAP wordt breed gewaardeerd en overgenomen door bedrijfstoepassingen omdat het gegevensmodellen strikt afdwingt en het openbare interfaces beschrijft via WSDL, waardoor sommige ontwikkeltools (zoals Microsoft Visual Studio voor .NET) automatisch objecten en methoden kunnen instellen om te consumeren. de services alleen door een verwijzing naar de service WSDL aan het project toe te voegen.

XML is echter bij-ontwerp minder efficiënt dan JSON bij het werken in een bandbreedtebeperkt netwerkscenario zoals mobiele ontwikkeling. Mobiele datanetwerken (WWAN's) zijn meestal minder betrouwbaar dan bekabelde (LAN) of draadloze (WLAN) netwerken, omdat clients onderweg gemakkelijk in en uit de dekkingsgebieden kunnen vallen. Sommige gebruikers abonneren zich ook niet op 'platte' gegevensabonnementen en worden feitelijk in rekening gebracht door netwerkverkeer.

Dus, terwijl u zich ontwikkelt voor mobiel, moet u altijd kiezen voor eenvoud en verkeersvermindering.

Laten we gewone XML vergelijken met JSON met een voorbeeldantwoord:

XML

  Hallo, apparaat! 

JSON

 returnValue: "Hallo, apparaat!" 

Zoals je kunt zien, JSON heeft een kleinere payload omdat het zijn gegevens alleen hoeft in te pakken met haakjes (gekruld voor objecten, vierkant voor arrays) en aanhalingstekens, terwijl XML een volledig basisknooppunt en tags voor het openen en sluiten van elk element of groep nodig heeft. Door op deze tags te besparen, kunt u de responspayload aanzienlijk verkorten en hoe meer gegevens u overdraagt, hoe groter de payload-opvulling bij XML is.

Bovendien vereisen SOAP en XML-RPC meer complexe XML-datastructuren (zoals de SOAP "envelope"), wat extra gewicht toevoegt aan de payload.

Om deze reden raad ik aan te kiezen JSON voor het gegevensuitwisselingsformaat van uw app en RUST UIT voor het overdrachtsprotocol, tenzij XML, SOAP of XML-RPC expliciet vereist zijn voor uw behoeften. Als u een gegevensmodel moet afdwingen, kunt u dat ook met JSON bereiken door het JSON-schema of WSDL 2.0 te gebruiken.

Zie het volgende voor verwijzingen en verder lezen over de besproken protocollen en gegevensindelingen:

  • Het JSON vs. XML-debat
  • JSON-overzicht
  • XML-overzicht
  • XML-RPC-overzicht
  • SOAP-overzicht
  • De JSON-homepage
  • Meer over WSDL

Overwegingen bij netwerkbeveiliging

Aangezien de meeste webservices werken via openbare netwerken, is het beschermen van de gegevens die worden uitgewisseld tussen de services en de app een van de meest kritieke problemen die u moet aanpakken. Veel webservices bieden externe functionaliteit voor geverifieerde gebruikers, dus privégegevens en verificatiegegevens moeten ook via het netwerk worden overgedragen.

Persoonlijke gegevens, accountgegevens en inloggegevens zouden dat moeten doen nooit reis in cleartext-vorm via een openbaar netwerk, dus dit betekent dat uw webservices en apps cryptografie moeten implementeren. Het goede nieuws is dat de meest voorkomende protocollen gegevens via HTTP transporteren, zodat u kunt vertrouwen op de bekend, vertrouwd en robuust HTTP SSL / TLS-protocol (HTTPS) met een brede ondersteuning zowel aan de serverkant als aan de clientzijde.

SSL inschakelen op gewone webservers is vrij eenvoudig (er zijn veel nuttige bronnen voor Apache, IIS en Nginx). Het enige wat u hoeft te doen is een SSL-certificaat kopen en dit op uw server installeren. In een in het slechtste geval, je zou ook een zelfondertekend certificaat kunnen uitgeven dat je gratis versleuteling zal brengen, maar dat zou ik doen niet beveel dit aan. Sommige CA's geven goedkope certificaten uit en de voordelen die u behaalt door te werken met een vertrouwd, ondertekend certificaat, zijn de extra kosten waard (dat wil zeggen dat u man-in-the-middle-aanvallen voorkomt door gebruik te maken van de PKI). Het gebruik van zelfondertekende certificaten kan ook extra codering of zelfs applicatiespecifieke "hacks" vereisen, omdat sommige netwerkbibliotheken niet-vertrouwde HTTPS-verbindingen weigeren (bekijk deze artikelen over Android, # 1 en # 2, en over iOS).

Het inschakelen van SSL aan clientzijde is een geruststelling: veelgebruikte programmeertalen hebben meestal HTTP-klassen en bibliotheken die native HTTP-SSL-ondersteuning bieden en "automagisch" zorgen voor codering door alleen "https: //" URL's te gebruiken in plaats van "http : // "URL's om webservices te gebruiken.

Als u kiest voor een laaggeprijsd SSL-certificaat, zorg er dan voor dat de apparaten en besturingssystemen die u wilt ontwikkelen het CA-hoofdcertificaat van de uitgever standaard gebundeld hebben, anders zullen zij het certificaat niet vertrouwen.

Je moet nooit gebruikers vragen om hun systemen te patchen, aan te passen of te hacken om je apps te kunnen gebruiken. Als je dat doet, verwacht dan niet dat veel van hen zullen voldoen.

Web Service-verificatie

Authenticatie voor REST-gebaseerde services

Op token gebaseerde verificatie

Web Services-transacties zijn bedoeld om te zijn atomair, interoperabele en schaalbaar, dus Web Services zijn meestal staatloze (bekijk deze interessante discussie over de betekenis van "staatloze" verbindingen).

Veel webservices bieden gebruikersgerelateerde functionaliteit en toegang tot gevoelige informatie. Uiteraard vereist dit authenticatie. Omdat dergelijke transacties stateless zijn, moest u traditioneel verzoeken ondertekenen met een gebruikersspecifieke sleutel, waarmee u authenticatie bij elke externe methode-aanroep krijgt. Zelfs wanneer gegevens worden overgedragen via HTTPS, lopen gebruikersreferenties het meeste risico wanneer ze via een openbaar netwerk worden verzonden. Encryptie is soms verbroken.

Dit dilemma is waar token-gebaseerde authenticatie zoals OAuth van pas komt. Met behulp van token-gebaseerde authenticatie, hoeft u de gegevens van een gebruiker slechts eenmaal te verzenden. Als de gebruiker met succes is geverifieerd, worden deze voorzien van tokens die kunnen worden gebruikt voor de verificatie van volgende externe methode-aanroepen.

De geldigheid van een token loopt over een beperkte levensduur en kan op elk moment worden ingetrokken door de uitgever (dat wil zeggen aan de serverzijde). Met token-gebaseerde authenticatie kunt u dezelfde gebruikersreferenties delen tussen verschillende apps en services zonder dat de gekoppelde services / apps ooit de echte gebruikersreferenties kennen. Verder houdt deze authenticatiemethode veilig een lokale cache van de referenties op het apparaat van de gebruiker, zodat de gebruiker kan worden "onthouden" en niet elke keer hoeft te worden geverifieerd dat hij de app zal gebruiken (typen van complexe wachtwoorden op rekenmachines kan een echte pijn en kan app-reviews zwaar beschadigen).

OAuth-gebaseerde verificatie

OAuth is het meest gebruikelijke op tokens gebaseerde autoraamwerk en het is overgenomen door grote spelers zoals Google, Twitter, Facebook, enzovoort. Door gebruikers toe te staan ​​hun bestaande accounts opnieuw te gebruiken, vervelende registratieformulieren over te slaan en de toegang tot hun persoonlijke gegevens te behouden, kunt u uw gebruikersbestand aanzienlijk vergroten..

Sommige OAuth-providers vereisen dat hun eigen SDK wordt geïmporteerd in uw apps om verificatie in te schakelen, anders zijn er veel kant-en-klare OAuth-bibliotheken rond die u kunt aansluiten op uw app. Er zijn ook frameworks zoals oauth-php beschikbaar om aangepaste OAuth-providers te bouwen.

Ik zou een wegwijzer voorstellen als een Android OAuth-clientbibliotheek en als userconsument voor iOS.

Al deze bibliotheken worden geleverd met handige voorbeelden en zijn eenvoudig te implementeren. Het kan echter lastig zijn om de bronnen met wegwijzers op uw computer te bouwen of ze in uw app te importeren, maar u hoeft dat proces niet echt te doorlopen. In plaats daarvan kunt u de JAR-binaries gewoon in uw project importeren en moet u worden ingesteld. Op iOS zou dit vergelijkbaar zijn met het importeren van een statische bibliotheek (* .a-bestand) in uw project.

Authenticatie voor op SOAP gebaseerde services

De meest gebruikelijke authenticatiemethode voor op SOAP gebaseerde services is een SOAP-extensie genaamd HTTP Basic Authentication (ook wel Digest-verificatie genoemd). Dit is een standaard, goed onderbouwde procedure die is geïntegreerd in alle meest voorkomende webservers zoals Apache, Nginx en IIS. Het is gebaseerd op een gebruikersnaam / wachtwoord-paar dat via HTTP-headers naar de server moet worden verzonden.

Normaal gesproken hoeft u basisauthenticatie niet handmatig in uw toepassingen te implementeren, omdat dit ook in de meest gangbare programmeertalen breed wordt ondersteund. Het .NET-framework maakt gebruik van de NetworkCredential-klasse voor het leveren van basis- en digestauthoremissies aan HTTP-aanvragen, PHP ondersteunt het via cURL en Java via Authenticator.

Als u Basic Auth zelf moet implementeren, hoeft u alleen maar deze header aan uw verzoeken toe te voegen:

 Basic gebruikersnaam: wachtwoord

De waarden "gebruikersnaam" en "wachtwoord" moeten zijn Base64 gecodeerde.

Let op dat HTTP Basic Auth kan het beste worden gebruikt in combinatie met het HTTPS-protocol, terwijl het inloggegevens overdraagt platte tekst het formulier. Digest Auth is een beetje veiliger, omdat het eigenlijk de wachtwoordwaarde hashes, maar HTTPS wordt sowieso aanbevolen om hash bruteforce-aanvallen te voorkomen.

Meer details en specificaties over dit onderwerp zijn te vinden in de IETF RFC 2617 memo.

Native Platform Authentication Libraries

Bij het kiezen van een authenticatiemethode of het integreren van bekende services (zoals sociale netwerken), moet u ook rekening houden met de native bibliotheken die zijn ingebouwd in veel geavanceerde platforms zoals iOS en Android. Dit kan u veel tijd en veel regels code besparen.

Android biedt een goed raamwerk voor het centraliseren van gebruikersaccountbeheer, de klasse AccountManager. De officiële Android-ontwikkelaarshandleiding bevat een aantal aardige documentatie voor deze klasse, samen met enkele tips om OAuth 2 te integreren of om uw eigen "Aangepaste accounttype" te schrijven.

Met iOS 6 heeft Apple een nieuw sociaal raamwerk geïntroduceerd om belangrijke diensten zoals Twitter, Facebook en Sina Weibo op OS-niveau te integreren. Zelfs als u deze services niet in uw toepassing hoeft te integreren, vindt u misschien een geschikte manier om te profiteren van de ingebouwde verificatiemethoden via aanpassing.


Optimalisatietips

Data compressie

Bij het ontwikkelen voor mobiele toepassingen is het belangrijk om uw datadatladingen zo laag mogelijk te houden. In dit gedeelte worden verschillende strategieën besproken om dit te doen.

Gegevens archiveren

ZIP-compressie kan tekst en ook binair gegevensgewicht aanzienlijk verminderen en wordt op de meeste platforms goed ondersteund, dus maak er goed gebruik van als u grote hoeveelheden gegevens via mobiele netwerken wilt overbrengen. Handige bibliotheken voor het beheer van ZIP-bestanden zijn beschikbaar voor Android (dat wil zeggen decomprimeren) en iOS (dat wil zeggen, ziparchive).

Efficiënte mediastreaming

Als u audio- / video-inhoud naar uw mobiele apps wilt streamen, kiest u geavanceerde streamingplatforms waarmee u streams kunt schalen, afhankelijk van de netwerk- / apparaatprestaties, zoals het HTTP Live Streaming (HLS) -protocol van Apple. Anders is het kiezen van reacties op mediakwaliteit meestal een goede keuze. Speel met verschillende video- en audiocompressoren en -instellingen, optimaliseer zoveel mogelijk. U kunt apparaten ook groeperen op soort (handhelds op klein scherm, breedbeeld-rekenmachines en tablets) en verschillende inhoud voor elke soort leveren.

Het probleem met HD

Veel mobiele apparaten hebben HD-schermen, maar is HD-inhoud op kleine schermen echt de extra bandbreedtebelasting waard? Wees eerlijk over de relevantie van mediakwaliteit in uw apps en probeer de beste balans tussen kwaliteit en gewicht te vinden.

Lokale caching

Laten we veronderstellen dat je een reader-app codeert voor een online krant. Allereerst moet u uw gebruikers altijd wanneer mogelijk offline laten werken. Hoewel sommige apps altijd een actief netwerk vereisen (zoals messaging-services), moeten vele anderen het netwerk alleen gebruiken voor download datapakketten en cacheer ze op het apparaat.

Dit zal de prestaties van de applicatie verbeteren, het geld van gebruikers besparen op niet-platte mobiele data-abonnementen en de app bruikbaar maken wanneer het netwerk niet beschikbaar is (bijvoorbeeld tijdens de vlucht).

Wanneer u inhoud downloadt op apparaten die externe opslag koppelen (bijvoorbeeld geheugenkaarten), moet u gebruikers laten kiezen waar ze gedownloade inhoud moeten opslaan (dat wil zeggen interne of externe opslag) of gewoon de voorkeur geven aan externe opslag. Apparaten op instapniveau hebben meestal een vrij kleine interne opslag en kunnen onstabiel of traag worden als de interne opslag vol is. Als uw apps veel opslagruimte in beslag nemen, worden ze waarschijnlijk gedeïnstalleerd om ruimte te besparen.

Chunking-gegevens

Laten we teruggaan naar het voorbeeld van de leeshulp. Elk artikel is één stuk, en hoewel artikelen aan elkaar kunnen worden gekoppeld, is er geen reden waarom gebruikers niet moeten beginnen met het lezen van artikelen, ook al wordt er nog steeds extra inhoud gedownload. Verpak dus de bestanden van elk artikel (tekst, afbeeldingen, bijlagen en media) in afzonderlijke ZIP-archieven en bieden een webservicemethode voor de app om de lijst met beschikbare artikelen. Laat je app ZIP-pakketten downloaden een voor een en maak ze dan beschikbaar in de app zodra elke is gedownload en terwijl anderen op de achtergrond worden gedownload. Dit is een geweldige verbetering van de prestaties en gebruikerservaringen vergeleken met wachten totdat de volledige payload is gedownload! U kunt gebruikers ook laten kiezen welke pakketten zij willen downloaden of niet (waardoor zij ruimte, tijd en verkeer kunnen besparen) en hen in staat stellen afzonderlijke pakketten te verwijderen om opslagruimte te besparen zonder de hele app te verwijderen.

Het volgende is een reactie van de demo server-app gebundeld met dit artikel:

 apiversion: 1, status: 0, packages: [file: "pack01_01_01.zip", package: "pack01", appversion: 1, revisie: 1, file: "pack01_02_01.zip", package: "pack01" , appversion: 2, revisie: 1, file: "pack02_01_01.zip", package: "pack02", appversion: 1, revisie: 1]

Verandermanagement

Houd er rekening mee dat uw app en eerder uitgebrachte inhoud in de loop van de tijd kunnen evolueren.

Voorzie een "revisie" -vlag voor elk pakket in de lijstmethode, dit is handig om updates vrij te geven, bugs in de inhoud op te lossen en de functionaliteit voor automatische updates in uw apps te implementeren. Zelfs als u niet van plan bent om automatisch bijwerken uit te voeren, moet u vooruit denken en de herzieningsvlag toch in uw lijst plaatsen voor toekomstige ontwikkeling.

U moet ook een vlag "app-versie" opnemen in uw pakkettenlijst. Als u een nieuwe belangrijke release van uw app uitbrengt die wijzigingen in het inhoudsformaat doorbreekt, kunt u hiermee content voor zowel nieuwere als oudere apps via dezelfde webservice aanbieden.


Fault Tolerance en Remote Data Recovery

Tijdens het ontwikkelen van service-gebaseerde apps, netwerk en apparaat fouttolerantie moet ook rekening worden gehouden. Mobiele gegevensverbindingen zijn meestal minder stabiel dan bekabelde, apps kunnen worden verwijderd en opnieuw geïnstalleerd en apparaten kunnen verloren gaan, worden vervangen door nieuwere of in de fabriek worden hersteld. Gebruikers moeten de mogelijkheid krijgen om apps en inhoud op een eenvoudige manier te herstellen en platformontwikkelaars bieden verschillende handige, kant-en-klare oplossingen voor deze problemen.

Netwerkstatus controleren

Onthoud om controleer altijd de netwerkstatus voordat u externe services belt of zorgvuldig netwerk-I / O-fouten verwerkt en uw gebruikers op de juiste manier informeert wanneer de gewenste taak niet kan worden uitgevoerd vanwege het ontbreken van een actieve gegevensverbinding. Moeten uw apps altijd "online werken", dan wilt u misschien een watchdog in uw apps plaatsen die constant de netwerkstatus bewaakt en een evenement in brand steekt telkens wanneer zich een verandering voordoet. Misschien wilt u gebruikers ook informeren over mogelijke extra kosten bij het overbrengen van grote hoeveelheden gegevens via 3G- of roaming-netwerken in plaats van via wifi.

Op Android-apparaten kan deze taak worden uitgevoerd via ConnectivityManager en via SCNetworkReachability op iOS (controleer ook de meegeleverde voorbeeldapp).

Inhoud en instellingen herstellen

Zowel Android als iOS bieden handige API's voor het verwerken van externe cloudback-ups van gebruikersapp-gegevens die u in gedachten moet houden. Raadpleeg de iCloud API-documentatie voor iOS en de Android Backup Service-documentatie voor Android. Samen met de ingebouwde back-upservices krijgt u ook goede functies voor gegevensbeveiliging. U moet er echter voor waken dat u geen back-upservices overlaadt met overbodige of onnodige back-ups.

U kunt ook aangepaste externe back-up van gegevens in uw webservices implementeren, maar ik raad u ten zeerste aan om zich te houden aan de standaarden en ingebouwde platform-API's. Ze besparen u meestal tijd en worden actief onderhouden door platform-software-engineers. OS-patches worden ook sneller geïnstalleerd zodra ze worden vrijgegeven.

In-app-aankopen herstellen

Als u betaalde inhoud via in-app-facturering in uw app levert, zodat gebruikers dit kunnen doen hun aankopen terugkrijgen nadat de app opnieuw is geïnstalleerd en het apparaat is hersteld verplicht. Gelukkig beschikken iOS en Android over ingebouwde API's om ook met deze scenario's om te gaan.

Wanneer uw apps die voor in-app-aankopen zijn ingeschakeld, voor de eerste keer worden uitgevoerd (of de eerste keer na een nieuwe installatie), moet u een procedure voor het controleren en terugzetten van aankopen uitvoeren. Zowel iOS als Android bieden leuke officiële documentatie over deze kwestie.

Denk er bij het ontwikkelen voor Android aan dat alleen "beheerde" items op een later tijdstip kunnen worden hersteld en dat ze alleen beschikbaar zijn bij een eenmalige aankoop per keer. Dit impliceert enkele overwegingen die ook van toepassing zijn op iOS-ontwikkeling.

Laten we veronderstellen dat je een rollenspel ontwikkelt en spelers de mogelijkheid wilt geven om items te kopen, zoals gezondheidsdrankjes, via in-app-facturering. Ten eerste omdat gebruikers zo veel drankjes kunnen kopen als ze willen, het kunnen geen 'beheerde' items zijn, dus hun aankooptransacties worden niet permanent opgeslagen. Als een gebruiker 20 drankjes koopt en 10 gebruikt, wordt het spel vervolgens op een later moment verwijderd en opnieuw geïnstalleerd. Als u de aankopen terugzet via een eenvoudige standaardprocedure, worden 20 drankjes terug in de inventaris van de gebruiker geplaatst, waarvan 10 een onbedoeld gratis geschenk van de ontwikkelaars.

U moet dus mogelijk uw eigen aangepaste webservices en app-methoden implementeren om transactieopslag en herstel af te handelen in complexe scenario's of edge cases.


Ontwerpen voor de toekomst

Deadlines en budgetten zullen u vaak afsnijden en niet toestaan ​​dat u alle best practices volgt die in dit artikel worden uitgelegd. Maar zelfs als je gedwongen bent om je aan een kleinere subset van functies te houden, denk vooruit, breng wat tijd door in goed ontwerp, en pak je methoden en klassen in bibliotheken die je later opnieuw kunt gebruiken en uitbreiden. Laat stompjes achter als je vindt dat er ruimte is voor verdere ontwikkeling. Probeer ook te handhaven achterwaartse compatibiliteit wanneer u uw bibliotheken uitbreidt en verbetert, zodat ook oudere toepassingen kunnen worden gepatcht.

Dit is een voorbeeld van een stub:

 public void sendData (Object data) if (validate (data)) client.send (data);  // Stub public Boolean validate (Object data) // TODO - Implementatie van data validatie return true; 

Conclusie: waar te gaan vanaf hier?

Als u een beginnende ontwikkelaar bent of nog nooit service-gebaseerde toepassingen hebt ontwikkeld, moet u uitgaan van de meegeleverde voorbeeldtoepassing als een goede oefening om uw kennis te verbeteren en er een toepassing van te maken die alle concepten die in dit artikel worden uitgelegd één voor één toepast tijd. U kunt ook een geheel nieuwe toepassing starten en deze integreren met een bestaande serviceprovider (Facebook, Twitter, Last.fm of Dropbox zou een goed startpunt zijn) volgens hetzelfde schema.

Als u al een aantal service- en netwerktoepassingen hebt ontwikkeld, kunt u uw bestaande code bekijken en deze verbeteren volgens de hierboven uiteengezette principes, waarbij u elke verbetering en impact op de prestaties en reactiesnelheid bijhoudt.

Vergeet niet ook de gelinkte bronnen te bekijken, omdat ze u dieper in de kern van elk probleem zullen leiden en de voorbeeldserver en clienttoepassingen die bij het artikel worden geleverd, zullen downloaden.