The correct way to send requests from Android to the remote server database

I am not very good at working with databases.

I have an Android application that needs to send queries and receive a subsequent result set from a remote sever database (MySQL).

I did this by actually sending the request as JSON to the server. Then the script server (PHP) retrieves the request and executes it. Then the result set is parsed into JSON again and sent back to the Android application.

My php script

function run_query(mysqli $con, $query){ $res=$con->query($query); return $res; } $reply = array(); if(isset($_POST['json'])) { require_once __DIR__.'/config.php'; require_once __DIR__.'/DbController.php'; $json = json_decode($_POST['json'], true); $query = $json['query']; $con = (new DbController())->connect(DBNAME); if(!$con){ $reply['suc']=false; $reply['err_msg']=$con->error; } else{ $res = run_query($con, $query); if(gettype($res)=="boolean"){ $reply['query_reply']=$res; $reply['suc']=true; die(json_encode($reply)); } $i=0; $reply['query_reply']= array(); while($row = $res->fetch_row()){ $reply['query_reply'][$i] = array(); for($j=0;$j<sizeof($row);$j++) $reply['query_reply'][$i][$j]=$row[$j]; $i++; } $reply['suc']=true; } echo json_encode($reply); } 

As you can see, the 'query' key contains the entire query string that is executed by the MySQL server.

My question is ... does it contain any protective (or other) loopholes that I do not know about? Also, is there a better way to do this?

One of my project assistants assumes that I have to cut the query into separate sections (Like- "query_type": "SELECT", "table_name": "LOGIN_TABLE", "where_args": "WHERE x = x" and so on) and send it to the server, and then restore the request there and execute.

However, I do not understand how this will help. Any suggestions would be appreciated. Thank you in advance.

+5
source share
4 answers

Your approach has a lot of problems. Anyone can reverse engineer your protocol and execute any query they want on your SQL server. Thus, your data is not only readable, but can be changed by anyone. In other words, you will be hacked.

The usual way is to split the cake into layers. This means defining an API built from clear and well-defined methods, with input parameter types, return values ​​and permissions.

This API can be implemented in any way: jsonrpc, SOAP, xmlrpc, your choice, even an HTTP GET for the returned php script jp file.

The latter option is a bit awkward, but also nice, as it allows you to use the same api from javascript running inside your site. There is no need to have two competing APIs.

Example:

API get_user_profile (user_id INT);

INPUT: integer user id

RETURNS: row in table users for this user, depending on their permissions.

Since the API is executing inside an authenticated session (using cookies or something else), it knows that the user is making a request. Thus, it will allow the user to see their phone number / email, but he will not return these fields to other users, unless they are administrators (which, of course, is possible with a simple example of permissions, more complex).

Thus, each operation requires its own API. Some of them are complex, for example, general search. Instead of writing your own mini-language and manipulating parameters to specify search parameters, you can simplify the situation by making it more or less look like a website. The client sends everything that the user enters into the search fields to the server (for example, an HTTP form), and the server decides how to deal with it.

Obviously, if any parameters of your API are directly inserted into SQL queries, then SQL injection means that you are also hacked. Therefore, you need to do it right, like on any website, everything that is exposed to malicious Internet is constantly attacked.

Think of the client as a browser, API calls as URLs, forms, xmlhttprequest, etc., and the server as PHP or any other server language. This is basically what it is.

+6
source

Rest api is the best way for android to remotely interact with the server. The HttpClient, volley, and Fast android libraries are some of the libraries that make it easy to communicate with api. HttpClient is too slow, so using HttpClient is not recommended. It is recommended that you use the fast Android network library because it is simple and fast.

Using the Android Fast Network Library

Android Networking Tutorial Tutorial

+1
source

The best way to communicate between the client application and the remote database is to use the RESTful API using the well-known HTTP GET, PUT, POST and DELETE requests. When you have a REST API , you can have multiple client-side applications using the same database, for example Android , IOS or JAVASCRIPT . And it will be protected by API_KEY , so only requests that are allowed to execute requests or modifications will be accepted.
There are many ways to create a REST API since you are a PHP developer. I would recommend the Slide Framework because it is lightweight and easy to use.

0
source

Suggestions 1: Add mySql user with specific permissions. or add permissions for sensitive tables, such as tables that have other user information ...

Suggestions 2: Create a passkey for each device, update it in each request and give a new passkey as an answer, if the passkey is invalid, ask the device to log in again. If the login is successful, enter the new device access key.

  • save crown to clean inactive devices at time intervals.
  • save passkey in SharedPreference on Android devices.

please check yql they had the same working idea

TRY THIS CLASS instead of volley

 public class SyncToServer extends AsyncTask<String,String,String> { Context context; String url; JSONObject jsonObjectToSend; JSONArray jsonArrayToSend; OnWebServiceListener onWebServiceListener; ProgressDialog progressDialog; /** * basic initializing, only use this contractor if you don't have anything to send. * @param context it can be null, if you don't want {@link ProgressDialog} pass it as null * @param url the url for data to be passed */ public SyncToServer(Context context,String url){ this.context=context; this.url=url+""; Log.e("SyncToServer123",url+""); if(context!=null) { progressDialog = new ProgressDialog(context); progressDialog.setMessage("loading"); progressDialog.setCancelable(false); } jsonObjectToSend=null; } /** * basic initializing, only use this contractor if you had anything to send. * @param context it can be null, if you don't want {@link ProgressDialog} pass it as null * @param url the url for data to be passed * @param jsonObject the {@link JSONObject} to pass server */ public SyncToServer(Context context,String url,JSONObject jsonObject){ this.context=context; this.url=url; this.jsonObjectToSend=jsonObject; if(context!=null) { progressDialog = new ProgressDialog(context); progressDialog.setMessage("loading"); progressDialog.setCancelable(false); } } /** * basic initializing, only use this contractor if you had anything to send. * @param context it can be null, if you don't want {@link ProgressDialog} pass it as null * @param url the url for data to be passed * @param jsonObject the {@link JSONArray} to pass server */ public SyncToServer(Context context,String url,JSONArray jsonObject){ this.context=context; this.url=url; this.jsonArrayToSend=jsonObject; if(context!=null) { progressDialog = new ProgressDialog(context); progressDialog.setMessage("loading"); progressDialog.setCancelable(false); } } /** * this method will register a callback, and start web service * @param onWebServiceListener this interface used to callback mechanism */ public void start(OnWebServiceListener onWebServiceListener){ Log.i("SyncToServer123","start"); this.onWebServiceListener=onWebServiceListener; this.execute(); } @Override protected void onPreExecute() { super.onPreExecute(); Log.i("SyncToServer123","init onPre"); if(context!=null) { progressDialog.show(); } } @Override protected String doInBackground(String... strings) { HttpClient client = new DefaultHttpClient(); Log.i("SyncToServer123","doIn"); try { InputStream is; HttpPost post = new HttpPost(url); HttpResponse httpResponse; if (jsonObjectToSend != null) { Log.i("SyncToServer123", jsonObjectToSend.toString()); StringEntity se = new StringEntity(jsonObjectToSend.toString()); Log.i("SyncToServer123", jsonObjectToSend.toString()); se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); post.setEntity(se); post.setHeader("Accept", "application/json"); post.setHeader("Content-type", "application/json"); post.setHeader("connection", "close"); httpResponse = client.execute(post); }else if(jsonArrayToSend!=null){ Log.i("SyncToServer123", jsonArrayToSend.toString()); StringEntity se = new StringEntity(jsonArrayToSend.toString()); Log.i("SyncToServer123", jsonArrayToSend.toString()); se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); post.setEntity(se); post.setHeader("Accept", "application/json"); post.setHeader("Content-type", "application/json"); post.setHeader("connection", "close"); httpResponse = client.execute(post); }else{ HttpGet httpGet=new HttpGet(url); httpGet.setHeader("connection", "close"); httpResponse = client.execute(httpGet); } HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); try { BufferedReader reader = new BufferedReader(new InputStreamReader( is, "iso-8859-1"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + ""); System.out.println(line); Log.i("SyncToServer123","PRE RESPONDS : "+line); } is.close(); String json = sb.toString(); JSONObject jObj; jObj = new JSONObject(json); Log.i("resultJson",json); Log.i("SyncToServer123","RESPONDS : "+json); reader.close(); httpEntity.consumeContent(); if(client != null && client.getConnectionManager() != null) { client.getConnectionManager().shutdown(); } return json; } catch (Exception e) { Log.i("SyncToServer123","Error "+e); Log.e("Buffer Error", "Error converting result " + e.toString()); } //customDbHelper.notifiSyncCompleted(); } catch (Exception e) { Log.i("SyncToServer123","Error "+e); e.printStackTrace(); } return null; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); System.out.print("SyncToServer123: "+s); if(s!=null){ this.onWebServiceListener.onComplete(s); }else{ this.onWebServiceListener.onError(); } if(context!=null) { progressDialog.dismiss(); } } /** * for callbacks the web service status, */ public interface OnWebServiceListener{ /** * when service completed without any exception, including {@link JSONException} * @param result the responds given from server */ void onComplete(String result); /** * if any exception occurred this method will call */ void onError(); } } 

USING

 SyncToServer syncToServer=new SyncToServer(null,"url",jsonObject); syncToServer.start(new SyncToServer.OnWebServiceListener() { @Override public void onComplete(String result) { } @Override public void onError() { } }); 

Library used

  useLibrary 'org.apache.http.legacy' 
0
source

Source: https://habr.com/ru/post/1271338/


All Articles