Android: Mysql, php, json, http and security - php

I'm quite new to the Android and Java world; I'm trying to develop an app that need to get and insert information in a database.
I searched on the net, and I found that the best solution is to use HTTP connection using PHP files with Jsons outputs as an interface between the application and the Mysql Db.
However, I can't figure out how to 'secure' everything.
Example:
To change the nickname of an user i connect my app to a php page with this code:
$nickname = $_POST['nickname'];
$id = $_POST['id'];
nicknameChange($id,$nickname);
function nicknameChange($id,$nickname){
global $mysqli;
$sql = "UPDATE users SET nickname = ? WHERE id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('si',$nickname,$id);
$stmt->execute();
}
Via post i pass the id of the user that wanna change nickname and the new nickname, how can i be sure that no one will 'manipulate' that page passing to it ids of other users to change their nickname?
I read on the Net that an HTTPS connection may solve the problem, is that enough?

In your client (android) and in server(php) you need use a key like 'API KEY'
In server
$message = 'Access denied';
$checkApi = false;
if(function_exists('apache_request_headers')){
if(apache_request_headers()['Authorization'] == '2d30ff242f8650954bfe8c993f084f4f')
$checkApi = true;
}
or
if(isset($_SERVER["Authorization"]) && $_SERVER["Authorization"] == '2d30ff242f8650954bfe8c993f084f4f'){
$checkApi = true;
}
Client: in your request you will put string '2d30ff242f8650954bfe8c993f084f4f' with key 'Authorization' to Header request.
This is a private key!

Related

How to use Binding in Xamarin.Forms (.XAML) using php script and MySQL?

NEED HELP
We are creating a Cross platform application in xamarin (Android / IOS). We have made a login system in our app by passing everytime when user is logged in, the Id of the user from the database. This Id is send to other pages in our app so that we could use this Id to access the other information (in other pages in our app) of that specific user with the specific Id.
Example:
We passed the Id to the profile page of the user that is logged in. As you can see in the screen beneath we want to get the username of that user so that we could use it in our app.
When we pass the Id using a HTML page we get the correct data from the database as you can see. It is this content we want to show instead of "Username" (frist picture).
The php-script we used to get this data out of our database (don't worry about mysql-injection the app is jsut for us we will change this later):
<?php
$db = new mysqli('localhost', 'root', 'Antjim0809!','sendmeadrink_official');
$Id = mysqli_real_escape_string($db, $_POST['Id']);
$res = mysqli_query($db, "SELECT Username from User WHERE Id = '$Id'");
while ($row = $res->fetch_assoc())
{
echo $row['Username'];
}
mysqli_close($db);
?>
But when we try to get this information using Xamarin we get the 'null' instead of 'Lucino23' as you can see in the output:
The Xamarin code of our Profile page looks like this (ProfilePage.XAML):
<Label Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding Username}"
FontAttributes="Bold"
FontSize="30"/>
The code behind (ProfilePage.XAML.cs)
readonly HttpClient client = new HttpClient(new HttpClientHandler());
readonly user u = new user() { Id = string.Empty, Username = string.Empty, Email = string.Empty, Passwd = string.Empty, Age = string.Empty };
public async void GetUserData(string Id)
{
HttpResponseMessage res;
u.Id = Id;
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("Id", u.Id)
});
res = await client.PostAsync("http://10.0.2.2/*/*/*/UsernameById.php", content);
u.Username = await res.Content.ReadAsStringAsync();
Console.WriteLine("-----------------------------------------");
Console.WriteLine(u.Username);
Console.WriteLine("-----------------------------------------");
}
I resume: When we apply all the code above, the 'Username' (Picture 1) is empty and we cannot see the Username that tis stored in the database. So we want to replace the 'Username' by the string value in our database of a specific user that is logged in.
Thanks to all!

Postpone HTTP GET response until the user changes the value in the database

I have a NodeMCU (ESP8266) board that sends HTTP GET requests to a shared hosting database. To avoid port forwarding on my router I came up with a solution where my NodeMCU board periodically sends (every 5 seconds) a HTTP GET request to the database to see if the device status is changed by the user.
void loop()
{
HTTPClient http; //Declare object of class HTTPClient
String getData, Link;
//HTTP GET REQUEST
getData = "?device="+ deviceName ;
Link = "http://.../getStatus.php" + getData;
http.begin(Link);
int httpCode = http.GET(); //Send the request
String payload = http.getString(); //Get the response from database
if(payload=="ON")
{
digitalWrite(LEDPin, HIGH);//change pin status
}
else if(payload=="OFF")
{
digitalWrite(LEDPin, LOW);//change pin status
}
http.end();
delay(5000);//Send GET request every 5 seconds
}
The user changes the device status over a website (with a button click) and the device status is then saved in the database. When the device sends the HTTP GET request to the server the getStatus.php file queries the database for the current device status and sends the response back to the device.
<?php
$db = mysqli_connect(...);
if(!empty($_GET['device']))
{
$device_name = $_GET['device'];
$query_status = "SELECT status FROM devices WHERE device = ?";
$stmt = mysqli_prepare($db, $query_status);
if ($stmt === false) {
error_log(mysqli_error($db));
die("Sorry, there has been a software error");
}
$ok = mysqli_stmt_bind_param($stmt, "s", $device_name);
if ($ok === false) {
error_log(mysqli_stmt_error($db));
die("Sorry, there has been a software error");
}
$ok = mysqli_stmt_execute($stmt);
if ($ok === false) {
error_log(mysqli_stmt_error($db));
die("Sorry, there has been a software error");
}
$result = $stmt->get_result();
if ($result->num_rows > 0)
{
while($row = $result->fetch_assoc())
{
echo $row["status"];
}
}
}
?>
I am trying to find a solution where I don't have to query the database every 5 second, but instead only when the user changes the device status.
So my question is how postpone the HTTP GET response until the moment that the user changes the device status with a button click?
You need a live connection between your device and server.
Socket is a good solution i think.
you can see this article :
https://blog.tommyku.com/blog/communication-between-cpp-and-php-program-using-socket/
to get help.
But personally i always prefer easy and fast ways with less change in my codes.
So :
instead get involved with complex socket programming
you can use in-memory data structure store like https://redis.io/ which response very faster than Mysql without any serious side-effect in your server (Php script) and then you don't need to change
NodeMCU(ESP8266) codes but Php code to use Redis.
"It's not a bug, it's a feature."
PHP was designed specifically to avoid these kind of notifications, and with good reason: They're an extremely vulnerable attack vector. If you're doing this in a production environment, I'd strongly suggest against this particular data-flow. In essence, what you're needing to do is turn the client into a server that accepts a connection from another server... a client server that doesn't have the reliable layers of security that your server (probably) has.
Now, that is annoying for those of us who actually want to do it. However, there is a recommended work-around without sacrificing your security. PHP is pretty much, hands down, the most secure language for the web. And it's not giving up that anytime soon. And this kind of situation where the standard solution is "use another language."
What you do is set up what's known as a push notification server. It's whole goal is a secure receiver go-between for less secure data transmissions. You have your database server communicate with the push server (which is likely nodejs or similar with a simple RESTapi for your database server). And you have a javascript your client uses that listens ONLY for a hash from that push server that corresponds with a hash supplied for their session for notifications. Then, when your push server gets pinged, it sends the information-less hex hash (which is purged of any non-hex information for security) at which point your front-end client knows "Hey, I should poll the server for additional information." At which point it does, and then you can let the client know what has updated.
I'd like to suggest that your current solution is fine.
You have a device that needs to know a value that's store in a remote database. As far as the device is concerned, the value could change at any time, and the device needs to update its own state when the remote value changes.
Having it act as a Host that receives connections or notifications of any kind from the remote server would probably be problematic. You mentioned that you'd have to set up port-forwarding. You'd also be adding the security concerns of a Host server to this device, and you'd need to worry about maintaining a consistent IP address (or something).
The ideal solution will depend on what you're trying to accomplish. Why don't you want to poll the server every five seconds?
Of course the actual question you asked was
how [to] postpone the HTTP GET response until the moment that the user changes the device status with a button click?
Postponing the response is hardly a normal thing to do, and you're going to run into all kinds of problems with timeouts, which I'm not going to address here (for brevity), and it'll be a struggle to get your system to do anything else at the same time, but it can be done:
client device:
static DateTime lastUpdated = now();//or whatever
void loop()
{
HTTPClient http; //Declare object of class HTTPClient
String getData, Link, payload;
bool succeeded;
//HTTP GET REQUEST
getData = "?device=" + deviceName + "&lastUpdated=" + lastUpdated.asEpochInt(); //or whatever
Link = "http://.../getStatus.php" + getData;
try
{
http.begin(Link);
int httpCode = http.GET(); //Send the request
payload = http.getString(); //Get the response from database
succeed = true;
}
catch(TimeoutError te) //or whatever
{
succeeded = false;
}
if(succeeded)
{
lastUpdated = now()
if(payload=="ON")
{
digitalWrite(LEDPin, HIGH);//change pin status
}
else if(payload=="OFF")
{
digitalWrite(LEDPin, LOW);//change pin status
}
}
http.end();
//delay(5000); //send the next one right away.
}
host server
<?php
$db = mysqli_connect(...);
if(!empty($_GET['device']))
{
$device_name = $_GET['device'];
$threshold = DateTimeImmutable::createFromFormat('U', $_GET['lastUpdated'])
$query_status = "SELECT status FROM devices WHERE device = ? AND lastUpdated > ?";
$stmt = mysqli_prepare($db, $query_status);
if ($stmt === false) {
error_log(mysqli_error($db));
die("Sorry, there has been a software error");
}
$ok = mysqli_stmt_bind_param($stmt, "s", $device_name)
&& mysqli_stmt_bind_param($stmt, "s", $threshold->format('Y-m-d H:i:s'));
if ($ok === false) {
error_log(mysqli_stmt_error($db));
die("Sorry, there has been a software error");
}
$waiting = TRUE;
while($waiting)
{
$ok = mysqli_stmt_execute($stmt);
if ($ok === false) {
error_log(mysqli_stmt_error($db));
die("Sorry, there has been a software error");
}
$result = $stmt->get_result();
if ($result->num_rows > 0)
{
$waiting = FALSE;
while($row = $result->fetch_assoc())
{
echo $row["status"];
}
}
else {
usleep(100);
}
}
}//or else what?
?>
And we could take this even farther (make it even worse) by pushing our while loop down into the MySQL, but that would require learning the details of MySQL Stored Procedures, and no amount of internet points is worth that.
Just because you can, doesn't mean you should.

pass variable though URL for getting JSON

I have an app which loads data from a server and publish that data in the text view but there is a scene
<?php
define('HOST','xxxxxx');
define('USER','xxxxxxx');
define('PASS','xxxxx');
define('DB','xxxxxxx');
//Connecting to Database
$con = mysqli_connect(HOST,USER,PASS,DB) or die('Unable to Connect');
$sql = "select * from Leaderboard where email='test#test.com'";
$res = mysqli_query($con,$sql);
$result = array();
while($row = mysqli_fetch_array($res)){
array_push($result,
array('name'=>$row[1],
'rank'=>$row[2],
'accuracy'=>$row[3]));
}
echo json_encode (array("list"=>$result));
mysqli_close($con);
?>
this is my PHP file which gives JSON like this
{"list":[{"name":"Vipul S","rank":"1","accuracy":"80"}]}
and I am getting these values into my android app very easily using volley library but the thing is I need something to make that email variable dynamic because I am getting user email from users phone so I need to pass a variable to PHP through my android, so is there any chance that I can pass this through my URL which is written in android
my URL is: "http://thehostels.in/judgement_files/myleaderboard.php"
so can I pass the emails from URL that will be taken by PHP file through
$email=$_GET['userEmail'];
finally what I want is to that the JSON should change according to email that changes due to URL, I hope I made sense
You can pass email id in URL as
http://thehostels.in/judgement_files/myleaderboard.php?userEmail=test#test.com
and you can use this parameter in PHP as below
$email = $_GET['userEmail'];
$sql = "select * from Leaderboard where email='$email'";
For security reason you should use proper validation for email id.

Php web service.How to get data from a database?

I am developing an adroid app and I faced some trouble about php web service.
I want to get user type information form database and according to the answer I will do some process in the background.
So in my authentication code there is a area like this to get usertype;
function getUserType(){
$sql = "SELECT `usertype` FROM `login_test` WHERE username = '". $this->username2."'
AND password = '".$this->password2."'";
$result = mysqli_query($this->DB_CONNECTION, $sql);
if(mysqli_num_rows($result)>0){
return (?);
}
}
and my in my login code the message will be send here;
if ($userStatus) {
// user existed
// So log him to main page
$json['success'] = 1;
$json['message'] = 'Access Granted';
$json['usertype'] = 'Client';
echo json_encode($json);
Here I dont know how to access a certain field called 'usertype' in my table (I am really new in php) and how to return the value that I got.
Any help will be apreciated
P.S = $userStatus returns ture.
You could try doing this:
$sql = "SELECT * FROM `login_test` WHERE username = '$this->username2' AND password = '$this->password2'";
$result = mysqli_query($this->DB_CONNECTION, $sql);
return $result->fetch_object()->userType;
While please do keep in mind to use prepared statements.

PHP - Explain steps needed for my SSO authentication

I have built a lot of internal applications at my company. And my programming is on the the database/app level. Most of my applications have been using the same login/authentication class for years. However, said company wants everything going through their SSO authentication application. They have sent me their SSO application URL, the fields names they are passing, my sites actionURL, and my appKey.
All of my applications are on the same domain. I understand that I can set cookies to work on entire domain and have that set. Right now I am a bit stuck because I wrote some very simple test code. It is taking users to the SSO server and authenticating and sending the back over to my actionURL which is just my root of my domain.
So I am trying to request a URL that is behind my code, it shows that I need to be authenticated, passes me to the SSO app, and then I get passed back to my actionURL. What do I need on my actionURL to allow me to navigate through my apps.
Current code:
session_start();
if ($_POST && isset($_POST['digest']))
{
$digest = $_POST["digest"];
// set the session variables ...
$_SESSION['username'] = $_POST["firstname"]." ".$_POST["lastname"];
$_SESSION['firstname'] = $_POST["firstname"];
$_SESSION['lastname'] = $_POST["lastname"];
$_SESSION['email'] = $_POST["email"];
$_SESSION['uid'] = $_POST["uid"];
// Needed for key
$uid = $_POST["uid"];
$time = $_POST["time"];
// Read the property file with the key and URL so this won't go into the main code ...
// this sets $appKey and $safeurl
require_once("safe_login_properties.php");
$mykey = "".$uid.$time.$appKey;
$mydigest = md5($mykey);
if ($debugthis) // enable this for some debugging
{
$fp = fopen("DebugInfo.txt", "a");
fprintf($fp, "%s\n", date("H:i:s"));
foreach($_POST as $p => $v)
{
fprintf($fp, "POST: %s: %s\n", $p, $v);
}
foreach($_SESSION as $p => $v)
{
fprintf($fp, "SESSION: %s: %s\n", $p, $v);
}
fprintf($fp, "mykey: %s (uid: %s, time %s, key %s)\n", $mykey, $uid, $time, $appKey);
fprintf($fp, "posted digest: %s\n", $digest);
fprintf($fp, "mydigest: %s\n", $mydigest);
if ($digest == $mydigest)
fprintf($fp, "Digest match\n");
else
fprintf($fp, "***** digest does not match\n");
fclose($fp);
}
if ($digest != $mydigest)
{
die("Invalid login - expected digest does not match");
}
}
if (!isset($_SESSION['username']) || empty($_SESSION['username']))
{
// Read the property file with the key and URL so this won't go into the main code ...
// this sets $appKey and $safeurl
require_once("safe_login.php");
header("Location: ".$safeurl);
}
Additional info - All of my applications are mysql and php based. So I need to bring my mysql piece into it. I need something that says yes you are authorized, your username was passed over, and now we will look you up in the mysql database and use your corresponding row for rights/access. Does that make sense? Trying to write that part right now.
In your case, there has to be a mapping between the users in your MySQL db and the SSO server. A simple one would be an email address. A better one would be a GUID - globally unique ID. Whetever it is, the SSO server should pass a unique ID identifying the user when it calls your actionURL ( in SSO terms... your callback url).
Once you get the unique ID, retrieve the user from your MySQL DB using that ID. If he exists, log him in.
Normally, the SSO server will create a cookie which your applications can see. This should indicate if your user is logged in or not ( so you don't have to keep going back to the Server to authenticate a user).
HTH

Categories