web-dev-qa-db-fra.com

Sécuriser l'api php à utiliser dans Android

Je suis novice pour Android. J'utilise Android studio pour développer une application. Les choses que j'ai faites

  1. Créé un DB avec deux tables dans MySQL.
  2. Créé deux api's pour les méthodes GET et POST.
  3. Accès réussi aux deux api's

Ce que j'ai réalisé pour l'instant

  1. Capable de GET les données du GET api.
  2. Capable de POST données en utilisant le POST api

Ce que je dois faire maintenant

Je souhaite que mon API soit publiée en ligne, c'est-à-dire que je souhaite déployer mes services sur un serveur et y accéder. À ce stade, je suis en mesure de déployer les services sur le serveur et d'y accéder.

Maintenant, je veux mes services (api's) à sécuriser. Pour cela, j'ai recherché de nombreux articles et trouvé deux façons.

  1. Utilisez le framework yii. Quelqu'un m'a dit de l'utiliser car il sécurisait automatiquement le api's. Mais je ne sais pas avec certitude si c'est le cas ou non.
  2. Sécurisez manuellement le api's

Quant au point 1 le cadre sera utile mais il est nouveau pour moi et il faudra du temps pour coopérer avec lui car j'ai déjà créé les services web.

Pour le point 2 j'ai des informations

  1. en utilisant HMAC_SHA1
  2. DÉTECTION D'APPAREILS MOBILES À L'AIDE DE PHP

Les deux liens semblent être bons mais le lien 1 ne me donne pas beaucoup d'informations à ce sujet.

Évidemment, je veux sécuriser mes deux api's

Maintenant, la partie code

GET_DATA.php

require_once ('config.php');

$sql = "SELECT * FROM users";


$r = mysqli_query($con,$sql);

$result = array();

while($row = mysqli_fetch_array($r)){
array_Push($result,array(
    'Id'=>$row['Id'],
    'Name'=>$row['Name']
));}

echo json_encode (array ('users' => $ result));

POST_DATA.php

require_once ('config.php');

$return_arr = array();

$UserId=($_POST['UserId']);
$Latitude=($_POST['Latitude']);
$Longitude=($_POST['Longitude']);
$DateTime=($_POST['DateTime']);


$user_register_sql1 = "INSERT INTO `activity`(`Id`,`UserId`, `Latitude`,`Longitude`,`DateTime`) values (NULL,'".$UserId."','".$Latitude."','".$Longitude."','".$DateTime."')";
mysqli_query ($con,$user_register_sql1);
$row_array['errorcode1'] = 1;

J'ai un user class dont je reçois username et ID

JSONfunctions.Java

Cette classe est responsable de l'obtention des données à partir de api

 public static JSONObject getJSONfromURL(String url)
{

    String json = "";
    JSONObject jsonObject = null;
    try
    {
        HttpClient httpClientt = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse httpResponse = httpClientt.execute(httpGet);
        BufferedReader br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
        StringBuffer sb = new StringBuffer();
        String line = "";
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        json = sb.toString();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try
    {
        jsonObject = new JSONObject(json);
    } catch (JSONException e) {
        e.printStackTrace();
    }

    return jsonObject;
}

PutUtility.Java

Cette classe est responsable de la méthode POST

public void setParam(String key, String value) {
    params.put(key, value);
}

public String postData(String Url) {

    StringBuilder sb = new StringBuilder();
    for (String key : params.keySet()) {
        String value = null;
        value = params.get(key);


        if (sb.length() > 0) {
            sb.append("&");
        }
        sb.append(key + "=" + value);
    }

    try {
        // Defined URL  where to send data

        URL url = new URL(Url);

        URLConnection conn = null;
        conn = url.openConnection();

        // Send POST data request
        httpConnection = (HttpURLConnection) conn;
        httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        httpConnection.setRequestMethod("POST");
        httpConnection.setDoInput(true);
        httpConnection.setDoOutput(true);
        OutputStreamWriter wr = null;

        wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(sb.toString());
        wr.flush();

        BufferedReader in = new BufferedReader(
                new InputStreamReader(httpConnection.getInputStream()));
        String inputLine;
        response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    return response.toString();
}

MainActivity.Java

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    _latitude = (TextView)findViewById(R.id.latitude);
    _longitude = (TextView)findViewById(R.id.longitude);
    btn_get_coordinates = (Button)findViewById(R.id.button);
    btn_save_data = (Button)findViewById(R.id.btn_save);   


    btn_save_data.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if(UserId.toString()== "" || Latitude.toString() == "" || Longitude.toString() == "" || DateTime.toString() == "")
            {
                Toast.makeText(getApplicationContext(), "Data Not Saved !!!! Please select appropriate data to save", Toast.LENGTH_SHORT).show();
            }


            new ServiceLogin().execute(UserId, Latitude, Longitude, DateTime);

        }
    });

    // Download JSON file AsyncTask
    new DownloadJSON().execute();
}
    // Download JSON file AsyncTask
private class DownloadJSON extends AsyncTask<Void, Void, Void>
{

   @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage("Fetching Users....!");
        progressDialog.setCancelable(false);
        progressDialog.show();

    }

    @Override
    protected Void doInBackground(Void... params) {

        // Locate the Users Class
        users = new ArrayList<Users>();

        // Create an array to populate the spinner
        userList = new ArrayList<String>();
        // http://10.0.2.2:8000/MobileApp/index.php
        //http://10.0.2.2:8000/app/web/users/
        //http://192.168.100.8:8000/app/web/users/
        // JSON file URL address
        jsonObject = JSONfunctions.getJSONfromURL("http://192.168.100.9:8000/MobileApp/GET_DATA.php");

        try
        {
            JSONObject jobj = new JSONObject(jsonObject.toString());
            // Locate the NodeList name
            jsonArray = jobj.getJSONArray("users");

            for(int i=0; i<jsonArray.length(); i++)
            {
                jsonObject = jsonArray.getJSONObject(i);

                Users user = new Users();

                user.setId(jsonObject.optString("Id"));
                user.setName(jsonObject.optString("Name"));
                users.add(user);

                userList.add(jsonObject.optString("Name"));

            }
        } catch (JSONException e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }


        return null;
    }

    @Override
    protected void onPostExecute(Void args)
    {
        // Locate the spinner in activity_main.xml
        Spinner spinner = (Spinner)findViewById(R.id.spinner);

        // Spinner adapter
        spinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, Android.R.layout.simple_spinner_dropdown_item, userList));

        // Spinner on item click listener

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {


            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                textViewResult = (TextView)findViewById(R.id.textView);

                // Set the text followed by the position

                textViewResult.setText("Hi " + users.get(position).getName() + " your ID is " + users.get(position).getId());
                UserId = String.valueOf(users.get(position).getId());
                progressDialog.dismiss();
                _latitude.setText("");
                _longitude.setText("");
                Latitude = null;
                Longitude= null;

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                textViewResult.setText("");
            }
        });
    }


}

Comme je suis novice, je ne sais pas quoi faire dans le script php et quoi faire dans mon Android :(. Il serait très utile si quelqu'un pouvait guidez-moi ou donnez-moi un tutoriel que je suis.

Toute aide serait très appréciée.

20
Moeez

Pour sécuriser vos API, vous avez besoin d'un mécanisme pour détecter que la demande à l'API provient d'une source de confiance. De nombreux frameworks sont livrés avec cette fonctionnalité par défaut.

Cependant, vous pouvez simplement utiliser JSON Web Tokens (jwt) avec PHP pour ajouter une autorisation à vos demandes d'api

En savoir plus sur l'authentification basée sur les jetons à partir de cette page.

Découvrez ceci tutoriel simple sur la façon de sécuriser vos PHP points finaux api avec JWT.

Si vous avez besoin d'encore plus de sécurité, vous voudrez peut-être ajouter OAuth service fournisseur à votre API. Consultez cet article sur comment écrire OAuth fournisseur en PHP

12
Dani Akash

La seule méthode pour sécuriser votre API est de faire votre Android demande d'être unique .Collectez des données plus spécifiques de votre application.

1 - Obtenez Android ID unique -

String UniqueID=Secure.getString(getActivity().getContentResolver(),Secure.Android_ID);

Et passez-le à travers votre api Eg.

http://192.168.100.9:8000/MobileApp/GET_DATA.php?yourvalue=something&id=UniqueID

Dans votre php, refusez l'accès s'il n'y a pas Android ID unique (devrait changer avec le nom de variable complexe) .Eg:

if($_REQUEST['UniqueID']=="" || strlen($_REQUEST['UniqueID'])<9){ //do something about abuse }else{ //your code }

2 - Créez votre propre variable aléatoire dans Android App

Créez votre propre variable pour décider de vous assurer que la demande provient de votre application Par exemple:

Random r = new Random();
int i1 = r.nextInt(9999 - 1000) + 1000;

Et passez également cette valeur via votre demande et validez quand il s'agit de php.

if($_REQUEST['r']>=1000 && $_REQUEST['r']<=9999){//}

Refuser la demande si elle ne passe pas ou si la valeur est incorrecte.

3 - Assurez-vous que les demandes proviennent d'Android

Je veux recommander d'utiliser la meilleure bibliothèque php gratuite http://mobiledetect.net/ Vérifiez si c'est de Android et écrivez la fonction de refus sur les abus invalides.

4 - Valider la demande via la chaîne User-Agent en PHP

$agent = $_SERVER['HTTP_USER_AGENT'];
$agent=strtolower($agent);

if (strpos($agent, 'Android') !== false) {
$os = 'Android';
}

Et niez sinon de Android en php.

5 - Enregistrez les attaquants

Vous devez suivre si quelqu'un casse l'un de vos titres ci-dessus. Actuellement, j'utilise ip-api.com pour suivre les attaquants.

vous devez écrire la fonction deny avec l'insertion mysql. selon ip-api, vous obtiendrez

1- IP des attaquants
2- Géolocalisation des attaquants
3- FAI des attaquants

Vous pouvez donc les refuser statiquement.

Il est sur le point d'utiliser votre API en toute sécurité à partir de Android et les demandes de PC presque refusées. Mais trois est une chance de casser votre application avec une ingénierie inverse comme dex2jar ou ShowJava et de saisir votre structure de données simple. un programmeur, les fonctions et les codes ci-dessus sont très faciles pour eux et ils entreront avec de fausses entrées de données.

Vous ne devez donc pas écrire un programme avec des valeurs statiques, un lien aussi important " http://192.168.100.9:8000/MobileApp/GET_DATA.php " aussi codé en dur que dans votre application. Vous devez diviser les données, chiffrer simplement et obtenir toutes vos URL principales dynamiquement comme ci-dessus pour la méthode sécurisée php/mysql api.

Si vous avez couvert tout comme un système dynamique en 2 étapes, il y a très très peu de chances de casser votre système.
Il me reste une chose importante à dire, si vous utilisez pour un groupe fermé d'utilisateurs, vous devez utiliser le système request-> approve pour chaque utilisateur pour la première inscription de l'application en utilisant leur ID unique et refuser facilement l'accès à les autres.

2
Aung Aung Swe

Ajoutez d'abord les dépendances dans build gradle (app)
implémentation 'com.mcxiaoke.volley: library: 1.0.16' Suivez ensuite le code ci-dessous:

 final ProgressDialog loading = ProgressDialog.show(getActivity(), "", "Please wait...", false, false);
        StringRequest stringRequest = new StringRequest(Request.Method.POST, ServerLinks.TOTAL_COUNT_URL, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                loading.dismiss();
                try {
                    JSONObject jsonObject = new JSONObject(response);

                    String status = jsonObject.getString("status");

                    if (status.equals("success")) {
                        String data = jsonObject.getString("data");

                        JSONObject jsonObject1 = new JSONObject(data);
                        String male = jsonObject1.getString("male");
                        String female = jsonObject1.getString("female");


                    } else {
                        // no_data_found.setVisibility(View.VISIBLE);
                        Toast.makeText(getActivity(), "No Data Found", Toast.LENGTH_SHORT).show();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }//onResponse()
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                loading.dismiss();
                //Toast.makeText(getActivity(), "Check Your Internet Connection", Toast.LENGTH_SHORT).show();
            }
        });
        int socketTimeout = 30000; // 30 seconds. You can change it
        RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

        stringRequest.setRetryPolicy(policy);
        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
        requestQueue.add(stringRequest);
0
Rock Mihar

Vous pouvez choisir votre authentification pour PHP ici:

http://pear.php.net/packages.php?catpid=1&catname=Authentication

Je pense que Basic ou Digest Auth (+ https: // SSL avec certificat auto-signé) sera un bon choix pour vous Rest-Service (PHP RESTful JSON API).

Pour Android je pense que le meilleur choix pour la bibliothèque RestClient est:

http://square.github.io/retrofit/

(Je vous recommande de conserver tout le code source dans une seule langue -Java. Vous pouvez facilement créer Java Rest Service et ajouter Spring Security Authentication)

0
sytolk

Utilisez le mécanisme de contrôle de session, toutes les méthodes ci-dessus parlent également de la même chose. En termes simples, utilisez une clé privée chiffrée pour détecter la source valide

0
Kushaal Singla
I will simply say, 

If you already using PHP OPP, then no need to go with any framework. It will be time consuming for you. 
Solution is: "Use remember_token system as like laravel and yii. Authenticate to each method before filter."

If you are using Core PHP. Try same code and include it before filter each method in your api
0
Heartbeat

sécuriser les API afin d'être accessible à un tiers est un vaste domaine à discuter. Le mécanisme le plus utilisé pour sécuriser les API est le contrôle d'accès basé sur des jetons. Il peut être mis en œuvre de plusieurs façons.

Vous devez d'abord comprendre comment cela fonctionne. Reportez-vous à cette lien et à cette lien .

Essayez ensuite de voir comment l'implémenter.

Exemple pratique d'implémentation de 'Token Based Authentication' en utilisant 'JSON Web Token (i.e.JWT)' dans PHP et MySQL?

Si vous avez besoin d'un exemple plus approfondi, essayez également link .

Si vous avez besoin de plus d'informations, faites-le moi savoir.

0
Techie