Android Tutorial HttpUtils2/PHP: GET vs POST methods

KMatle

Expert
Licensed User
Of course there is more about to secure data transmissions between clients & servers. Please take this tutorial to think about to secure your communication as good as you can.


With HttpUtils2 you can make requests to servers running PHP (Apache) or other components. This tutorial is about

- the common methods "GET" and "POST" in PHP
- the corresponding methods in HttpUtils2
- where the difference is
- security

Some contents were taken from http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post

When I first started to do an app with B4A I took a look at some examples here in the forum. What I needed was to send a bunch of parameters to a php script on my server. Very fast I cam across HttpUtils with the method "download2" which escapes all parameters (like slashes) which is very comfortable.

B4X:
Dim GetExample As HttpJob
GetExample.Initialize("GetExample", Me)
GetExample.Download2(servername & "/Serverfolder/GetExample.php",  _
                 Array As String("P1", "This is P1","P2", "This is P2", "P3", "This is P3"))
It just sends a GET-request with an array of parameters to the given server, path and the called script. Inside the script the parameters P1-P3 (array) can be retrieved like this:

B4X:
<?php

$p1=$_GET["P1"];
$p2=$_GET["P2"];
$p3=$_GET["P3"];

echo "Get-Example >>> P1:" . $p1 . " P2: " . $p2 . " P3: " . $p3;


?>
"$_GET" is a PHP command which gets the data from the associated parameter (= value of "P1")

Nice & very easy.

Taking a look to the server log "access.log" (Apache logs any request here) showed my request, to:

B4X:
192.168.178.23 - - [11/Mar/2016:20:40:00 +0100]
"GET //Serverfolder/GetExample.php?P1=This+is+P1&P2=This+is+P2&P3=This+is+P3
HTTP/1.1" 200 59 "-" "-"
Even if it's encrypted, one could copy it and use it again (bad: user login without further checks)

B4X:
192.168.178.23 - - [10/Mar/2016:22:18:33 +0100] "GET /enctrans/enctranssingle.php?Enc%3dLufIZSVR94zL5oQnHJlneWSOdnCrLFDdrv3vqHiL0lRTftogdIuf%2bamKX3%2f4C2xKXOsLvf%2bgMg7lAT20Q1G9E%2f%2f6W2Nn9rOwK%2biwQThTPGbbyPdUzDNaHaNywA03nusFjcBp6HZL5E612JBIat54%2fr2JxZwVnIyyua4HufVVrFcjHEON09U%2beLYOGQYwSGQPNkas%2b%2fFDaXFEc2ZR2Vj0oSpFLDe1rlggnxMbdD%2f%2bYHDPULq009A6yPve%2bmOUJSt8OaiRI%2f84YpWiE%2fQYRDG6oobwiaFbpIAh6H%2faFuCpGkaAcDNHzYtbyzHRwmzY4pyE2Hrc3qz03vO5f5J8zDgbwaC2zKlaKJGDIJZWaj3zmHdOoqerTfkRZhcHlnfUPJ60cfpt2kgVauSX8mrKJvBM2idaKxvm3S3YyXD1S5D5YOUhP%2b5u3wZI%2bNxJhWImfUk1RpCt1rmSPIpGNm5Nzox1On1Duxz5q58K7PxGwapiGSUMoZjWcGxmdGH0E1Jeul9O8RoSOTlDI2zwXWr1BHzapPMeNJAtp2OZj9gBSj
By the way: Typing "servername/Serverfolder/GetExample.php?P1=This+is+P1&P2=This+is+P2&P3=This+is+P3" in your favourite browser would do the same thing.

So this made me wonder a bit:

- Get requests can be seen at least by server admins
- the structure is obviously (the request can be modified or called n-times again with other data)
- existing server folders and scriptnames are public (security!)

Even worse:

  • GET requests can be cached
  • GET requests can remain in the browser history
  • GET requests can be bookmarked
  • GET requests can be distributed & shared
  • GET requests can be hacked
  • GET requests are limited (length)
So what about usig "POST" instead without using the PHP's post method? Grab all the data and use it instead of getting single fields.

B4X:
Dim PostExample As HttpJob
PostExample.Initialize("PostExample", Me)
PostExample.PostString(servername & "/Serverfolder/PostExample.php",SimpleString)
Hm. Not THAT comfortable. Before we had an array which could be expanded very easy. Now it's just a simple string.

One single string sounds good on the other side. It's just a simple string which can be encoded, encrypted and all the things we may want to do. It's much easier to do it with a simple string.

However. As I use a lot of JSON I then just created some similar (I'm lazy and I wanted the comfort of an easy expandable paramater list AND s simple string):

B4X:
Dim JsonList As List 
Dim JsonMap As Map
   
JsonList.Initialize
JsonMap.Initialize
   
JsonMap.put("P1", "This is P1")
JsonMap.put("P2", "This is P3")
JsonMap.put("P3", "This is P3")
   
JsonList.add(JsonMap)
  
Dim JSONGenerator As JSONGenerator
JSONGenerator.Initialize2(JsonList)
  
Dim JSONstring As String
JSONstring = JSONGenerator.ToString
I just put all the parameters in a (array) of maps and all of them in a List which is converted to a JSON-string to use it with "PostString".

The PHP-side:

B4X:
$JsonString = file_get_contents("php://input");

$JsonList = array();
$JsonMap = array();
$JsonList=json_decode($JsonString, true);
$x = 0;

while($x < count($JsonList)) {
    $JsonMap=$JsonList[$x];
   
    $p1=$JsonMap["P1"];
    $p2=$JsonMap["P2"];
    $p3=$JsonMap["P3"];

    echo "Post-Example >>> P1:" . $p1 . " P2: " . $p2 . " P3: " . $p3;
    $x++;
}


?>
file_get_contents("php://input") just gets all the data sent to the script (no matter which method). It can receive files, bytes, etc. Nice thing.

In the php script you can identify the same structure as the b4x code to create the JSON-List. Of course it can be done in other ways but I use these little code snippets in many of my b4x apps.

Back to the security benefits

Taking a look to the server log "access.log" again shows this:

B4X:
192.168.178.23 - - [11/Mar/2016:20:40:00 +0100] "POST //Serverfolder/PostExample.php
HTTP/1.1" 200 60 "-" "-"
As you can see, no data is shown (which is good). Of course an admin needs to see what is called and when (which is ok).

In the future I will use "POST" (PostString) methods as often as I can.

Although rules usually exist for good reasons, it’s good to know the logic behind them so they can be embraced fully. I, myself, hate rules that don’t have explanations and I hope that the above helps to justify the rules of GET vs POST.

Choosing between methods is a systematic process which should be part of second nature.
 

somed3v3loper

Well-Known Member
Licensed User
Thanks KMatle for your tutorials .
Can you please provide an example of a secure registration and login ?
Is "SELECT * FROM users WHERE user =. $p1 AND password = . $p2 " safe and OK ?
 

JNG

Member
Licensed User
Hi KMatle,

How I can send two different json string with poststring method.

regards
 

KMatle

Expert
Licensed User
Its a part of one job only but data is in two different json string
In my example the JSON-string contains all the data you want to post. So add all your data to the map/list and then convert it. There are tons of ways how to do it. This is ONE example.
 

KMatle

Expert
Licensed User
Can you please provide an example of a secure registration and login ?
Is "SELECT * FROM users WHERE user =. $p1 AND password = . $p2 " safe and OK ?
- it's all about the transport of the data
- use https and encrypt the data you post
- don't use methods which send a full query to your script (it can be modified)
- only send the raw data you use for your queries
- check/escape all the data in your script (see SQL injection)
- never store any login data (users, pw's, db-names) in your app

So if you send "SELECT * FROM users WHERE user =. $p1 AND password = . $p2" from your app I could easily change it to "SELECT * FROM users" which returns all users with the pw's :D
 
Last edited:

somed3v3loper

Well-Known Member
Licensed User
- it's all about the transport of the data
- use https and encrypt the data you post
- don't use methods which send a full query to your script (it can be modified)
- only send the raw data you use for your queries
- check/escape all the data in your script (see SQL injection)
- never store any login data (users, pw's, db-names) in your app

So if you send "SELECT * FROM users WHERE user =. $p1 AND password = . $p2" from your app I could easily change it to "SELECT * FROM users" which returns all users with the pw's :D
No I meant this SELECT statement is inside PHP file .

And if I should not store user password , how can my app log him in next time automatically ?

Sorry for asking a lot and Thanks again .
 

KMatle

Expert
Licensed User
And if I should not store user password , how can my app log him in next time automatically ?
Ok, if your app does financial transcations you must use https & RSA encryption (no automatic logins) :D

If it's just a simple login you could store the userid & pw to an encrypted file after the first successful login (see Random Access File). The pw for the file (every user has an own -> generate it when he first logs in -> 50 chars long) could be retrieved from the server after the app starts (storing it in your app could be retrieved by users with knowlege). At the next start you would get the file pw from the server again, decrypt the file and send the login data.

Pros: No pw is stored on the device (a encrpted file only)

Cons: Ok, the file could be copied to another device or someone could sniff his own pw (but how likely is that)

If you don't that additional security you could use a hardcoded pw in your app to en-/decrypt the file. It's not that safe but 90% of the users will not be able to hack that.
 

somed3v3loper

Well-Known Member
Licensed User
If it's just a simple login you could store the userid & pw to an encrypted file after the first successful login (see Random Access File). The pw for the file (every user has an own -> generate it when he first logs in -> 50 chars long) could be retrieved from the server after the app starts (storing it in your app could be retrieved by users with knowlege). At the next start you would get the file pw from the server again, decrypt the file and send the login data.
I am sorry I am not sure I fully understood that . Do we have a B4A example ?
 

Baris Karadeniz

Active Member
Licensed User
KMatle, I try to send location information with GET for iOS app. I use same codes as in your post#1. It says "responce sucsess and job is completed" in b4i log screen but there is not any log in the server. What can be the problem?

The codes are;

B4X:
Dim Job1 As HttpJob
      Job1.Initialize("MyJob", Me)
      Job1.Download2("http://domain/http/xxx.php", Array As String("op", gps, "imei", TextFieldimei.text, "dt", Location1.Time, "lat", Location1.Latitude, "lng", Location1.Longitude, "altitude", Location1.Altitude, "angle", Location1.Bearing, "speed", Location1.speed ))

Sub JobDone (Job As HttpJob)
    Log("Job completed: " & Job.Success)
    Job.Release
End Sub
 

Baris Karadeniz

Active Member
Licensed User
These codes were just an example, so url was not written. The codes with url is given below. As I said, "response success and job is completed" in b4i log screen but there is not any log in the server. What can be the problem?

B4X:
Dim Job1 As HttpJob
      Job1.Initialize("MyJob", Me)
      Job1.Download2("http://www.taksi-m.com.tr/track/server/http/android.php", Array As String("op", gps, "imei", TextFieldimei.text, "dt", Location1.Time, "lat", Location1.Latitude, "lng", Location1.Longitude, "altitude", Location1.Altitude, "angle", Location1.Bearing, "speed", Location1.speed ))

Sub JobDone (Job As HttpJob)
    Log("Job completed: " & Job.Success)
    Job.Release
End Sub
 

Baris Karadeniz

Active Member
Licensed User
The log of another android app (which is not developed by us) in the server is given below. May be array format in my code should be changed?

B4X:
GET /track/server/http/android.php op=gpsok&imei=354602060264434&dt=2016%2D05%2D11%2012%3A44%3A19&lat=40.16674&lng=26.420457&altitude=55&angle=218&speed=0&params=batp=73%7Cbats=0%7Cchat=1%7Ccost=0%7Coccupied=0%7C&event= 80 - 176.238.21.152 HTTP/1.1 - - - taksi-m.com.tr 200 0 0 201 278 62
 

Baris Karadeniz

Active Member
Licensed User
Project is also given attached. You should write IMEI number as 355696058830106 in status screen and turn system on (it should be green) to get location datas. May be "imei", TextFieldimei.text is wrong format. It may not get the numbers from the "TextFieldimei.text" You know better.
 

Attachments

Baris Karadeniz

Active Member
Licensed User
Because IMEI has to be registered server. If it is not registered to the server, server will not accept any data.

I established first connection. It is good news. But the location information is not taken by server. I try to do this now.
 
Top