Защита php api для использования в приложении Android


Я новичок в разработке Android. Я использую android studio для разработки приложения. То, что я сделал

  1. Создал DB с двумя таблицами в нем в MySQL.
  2. Создал два отдельных api's для обоих методов GET и POST.
  3. Успешный доступ к обоим api's

Чего я достиг на данный момент

  1. Способный GET Формировать данные для получения api.
  2. Возможность POST передавать данные с помощью ПОСТА api

Что я нужно сделать сейчас

Я хочу, чтобы мой api публиковался в Интернете, т.Е. Я хочу развернуть свои сервисы на сервере и получить к ним доступ. На этом этапе я могу развернуть службы на сервере и получить к ним доступ.

Теперь я хочу, чтобы мои услуги (api's) были защищены. Для этого я просмотрел множество статей и нашел два способа.

  1. Используйте yii фреймворк. Кто-то сказал мне использовать его, потому что он автоматически защищал api's. Но я не знаю наверняка, так ли это или нет.
  2. Вручную закрепите api's

Что касается пункта 1, то фреймворк будет полезен, но он для меня новый, и для взаимодействия с ним потребуется время, так как я уже создал веб-сервисы.

Для пункта 2 я получил некоторую информацию

  1. использование HMAC_SHA1
  2. ОБНАРУЖЕНИЕ МОБИЛЬНЫХ УСТРОЙСТВ С ПОМОЩЬЮ PHP

Обе ссылки кажутся хорошими, но ссылка 1 не дает мне много информации об этом.

Очевидно, я хочу обезопасить свои оба api's

Теперь часть кода

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(массив ('пользователи'=>$результат));

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;

У меня есть user class, из которого я получаю username и ID

JSONfunctions.java

Этот класс отвечает за получение данных из 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;
}

Бесполезность.Ява

Этот класс отвечает за 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("");
            }
        });
    }


}

Поскольку я новичок, поэтому я не знаю, что делать в скрипте php и что делать в моем коде Android:(. Было бы очень полезно, если бы кто-нибудь мог направить меня или дать мне учебник, которому я следую.

Любая помощь будет высоко оценена.

Author: Community, 2017-02-24

6 answers

Для защиты ваших API вам нужен механизм, позволяющий определить, что запрос к api сделан из надежного источника. Многие фреймворки поставляются с этой функцией по умолчанию.

Однако вы можете просто использовать Веб-токены JSON (jwt) с PHP для добавления авторизации в ваши запросы api

Узнайте об аутентификации на основе токенов из эта страница.

Проверьте это простой учебник о том, как защитить ваши конечные точки PHP api с помощью JWT.

Если вам нужна еще большая безопасность, вы можете добавить службу поставщика OAuth в свой API. ознакомьтесь с этим постом на как написать провайдера OAuth на PHP

 9
Author: Dani Akash, 2017-03-21 06:29:34

Единственный способ защитить ваш api - сделать ваш запрос Android уникальным.Соберите более конкретные данные из своего приложения.

1 - Получите уникальный идентификатор Android -

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

И передайте его через свой api, например.

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

В вашем php запретите доступ, если нет уникального идентификатора Android (следует изменить с помощью имени сложной переменной). Например:

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

2 - Создайте свою собственную случайную величину в приложении для Android

Создайте свою собственную переменную, чтобы принять решение о создании убедитесь, что запрос поступает из вашего приложения Например:

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

А также передайте это значение через ваш запрос и подтвердите, когда дело дойдет до php.

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

Отклонить запрос, если не передано или неверное значение.

3 - Убедитесь, что запросы поступают с Android

Я хочу порекомендовать использовать бесплатную лучшую библиотеку php http://mobiledetect.net / Проверьте, не с Android ли это, и напишите функцию запрета на недопустимые нарушения.

4 - Подтвердите запрос через строку Агента пользователя в PHP

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

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

И запретить, если не с Android в php.

5 - Запишите нападавших

Вам нужно отслеживать, не нарушает ли кто-то одну из ваших вышеуказанных ценных бумаг. В настоящее время я использую ip-api.com для отслеживания атакующих.

Вам нужно написать функцию запрета с помощью mysql insert. согласно ip-api, вы получите

1- IP-адрес злоумышленников
2 - Геолокация злоумышленников
3- Провайдер злоумышленников

Так что вы можете отрицать их статически.

Скоро будет безопасно использовать ваш api с Android и почти отклонять запросы ПК. Но три - это шанс сломать ваше приложение с помощью обратного проектирования, такого как dex2jar или Showjava, и захватить вашу простую структуру данных. Как программист, вышеперечисленные функции и коды для них очень просты, и они войдут с помощью поддельных вводов данных.

Поэтому вам не следует писать программу со статическими значениями, такая важная ссылка"http://192.168.100.9:8000/MobileApp/GET_DATA.php "как трудно закодировано так же, как в вашем приложении. Вы должны разделить данные, просто зашифровать и получить все ваши основные URL-адреса динамически, как описано выше, защищенным методом php/mysql api.

Если вы рассмотрели так же, как 2-ступенчатую динамическую систему, у вас очень мало шансов взломать вашу систему.
Мне осталось сказать одно важное замечание: если вы используете для закрытой группы пользователей, вам следует использовать систему запроса->утверждения для каждого пользователя при первой регистрации приложения, используя их уникальный идентификатор, и легко запретить доступ другим.

 2
Author: Aung Aung Swe, 2017-03-15 21:51:44

Защита API-интерфейсов для доступа третьей стороны - это обширная область, подлежащая обсуждению. Наиболее часто используемым механизмом защиты API-интерфейсов является контроль доступа на основе токенов. Это может быть реализовано многими способами.

1-й вам нужно понять, как это работает. Обратитесь к этой ссылке и этой ссылке.

Затем попробуйте посмотреть, как это реализовать.

Рабочий пример реализации "Аутентификации на основе токенов" с использованием "веб-токена JSON (т.Е. JWT)" в PHP и MySQL?

Если вам нужен более подробный пример, попробуйте также воспользоваться этой ссылкой .

Если вам нужна дополнительная информация, дайте мне знать.

 0
Author: Techie, 2017-05-23 12:32:08

Используйте механизм управления сеансами все вышеперечисленные методы также говорят об одном и том же. Проще говоря, используйте зашифрованный закрытый ключ для определения действительного источника

 0
Author: Kushaal Singla, 2017-03-21 07:31:57
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
Author: Heartbeat, 2017-03-21 07:37:33

Вы можете выбрать аутентификацию для PHP здесь:

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

Я думаю, что базовая или дайджест-аутентификация (+ https://SSL с самозаверяющим сертификатом) будет хорошим выбором для вас Rest-сервис (PHP RESTful JSON API).

Для приложения Android я думаю, что лучшим выбором для библиотеки RestClient является:

Http://square.github.io/retrofit/

(Я рекомендую вам сохранить весь исходный код только на одном языке - Java. Вы можете легко создать Службу Java Rest и добавить аутентификацию Spring Security)

 0
Author: sytolk, 2017-03-21 08:15:48