Защита php api для использования в приложении Android
Я новичок в разработке Android. Я использую android studio
для разработки приложения. Что я сделал
- Создал
DB
с двумя таблицами в ней в MySQL
. - Создал два отдельных
api's
для методов GET
и POST
. - Успешный доступ к обоим
api's
Чего я достиг на данный момент
- Способный
GET
данные формируют GET api
. - Возможность
POST
данных с помощью api
POST
Что мне теперь делать
Я хочу, чтобы мой API публиковался в Интернете, т.е. я хочу развернуть свои сервисы на сервере и получить к ним доступ. На данный момент я могу развернуть сервисы на сервере и получить к ним доступ.
Теперь я хочу, чтобы мои услуги (api's
) были защищены. Для этого я искал много статей и нашел два пути.
- Используйте рамки
yii
. Кто-то сказал мне использовать его, потому что он автоматически защищал api's
. Но я точно не знаю, так ли это или нет. - Вручную обеспечить
api's
Что касается пункта 1
фреймворк будет полезен, но он для меня новый, и потребуется время, чтобы с ним справиться, так как я уже создал веб-сервисы.
Для пункта 2
я получил некоторую информацию
- используя HMAC_SHA1
- ОБНАРУЖЕНИЕ МОБИЛЬНЫХ УСТРОЙСТВ, ИСПОЛЬЗУЮЩИХ 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 (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;
У меня есть 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;
}
PutUtility.Java
Этот класс отвечает за метод 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 :(. Было бы очень полезно, если бы кто-нибудь мог направить меня или дать мне учебник, которому я следую.
Любая помощь будет высоко оценен.
Ответы
Ответ 1
Чтобы защитить ваши API, вам нужен механизм для обнаружения того, что запрос на api сделан из надежного источника. Многие фреймворки поставляются с этой функцией по умолчанию.
Однако вы можете просто использовать JSON Web Tokens (jwt) с PHP, чтобы добавить авторизацию к вашим запросам api
Узнайте о аутентификации на основе токенов с на этой странице.
Ознакомьтесь с этим простым учебным пособием о том, как защитить ваши конечные точки PHP api с помощью JWT.
Если вам нужна еще больше безопасности, вы можете добавить сервис провайдера OAuth в свой API. прочитайте этот пост на как написать поставщика OAuth в PHP
Ответ 2
Единственный способ защитить ваш api - сделать ваш запрос на андроид уникальным. Выберите более конкретные данные из вашего приложения.
1 - получите уникальный идентификатор Android
String UniqueID=Secure.getString(getActivity().getContentResolver(),Secure.ANDROID_ID);
И передайте его через ваш api Eg.
http://192.168.100.9:8000/MobileApp/GET_DATA.php?yourvalue=something&id=UniqueID
В вашем php запретите доступ, если нет уникального идентификатора Android (следует изменить с именем сложной переменной).Eg:
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 и функция deny deny при неправильных нарушениях.
4 - Проверить запрос через строку User-Agent в PHP
$agent = $_SERVER['HTTP_USER_AGENT'];
$agent=strtolower($agent);
if (strpos($agent, 'android') !== false) {
$os = 'Android';
}
И отрицать, если не от android в php.
5 - Запишите нападавших
Вам нужно отслеживать, нарушает ли кто-то один из ваших вышеперечисленных ценных бумаг.
В настоящее время я использую ip-api.com для отслеживания злоумышленников.
вам нужно написать функцию deny с вставкой mysql.
согласно ip-api, вы получите
1- атакующий ip
2- геолокация атакующих
3-ISP-атакующих
Таким образом, вы можете отрицать их статически.
Он собирается безопасно использовать ваш api от android и почти отказал в pc-запросах. Но три - это шанс разорвать ваше приложение с помощью обратной инженерии, например
dex2jar или ShowJava и захватить вашу простую структуру данных.
Как программист, выше функции и коды очень легки для них, и они будут работать с поддельными входами данных.
Таким образом, вы не должны писать программу со статическими значениями, такую важную ссылку " http://192.168.100.9:8000/MobileApp/GET_DATA.php" как жестко закодированную, как в вашем приложении.
Вы должны разделить данные, просто зашифровать и получить все ваши основные URL-адреса динамически, как описано выше, с помощью метода php/mysql api.
Если вы накрыли как 2-ступенчатую динамическую систему, очень мало шансов переломить вашу систему.
Я хочу сказать, что если вы используете для закрытой группы пользователей, вы должны использовать систему request- > approve для каждого пользователя для первой регистрации приложений, используя свой уникальный идентификатор и легко отказывать в доступе от других.
Ответ 3
защищать API-интерфейсы для доступа третьей стороной - это обширный домен, который будет обсуждаться. Наиболее часто используемый механизм защиты API-интерфейсов - это контроль доступа на основе токенов. Его можно реализовать разными способами.
1 вам нужно понять, как это работает. Обратитесь к этой ссылке и этой ссылке.
Затем попробуйте посмотреть, как его реализовать.
Рабочий пример реализации аутентификации на основе токенов с использованием "JSON Web Token (т.е. JWT)" в PHP и MySQL?
Если вам нужен более подробный пример, попробуйте эту ссылку.
Если вам нужна дополнительная информация, дайте мне знать.
Ответ 4
Используйте механизм управления сеансом, все описанные выше методы также говорят о том же. В простых словах используется зашифрованный закрытый ключ для обнаружения действительного источника
Ответ 5
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
Ответ 6
Здесь вы можете выбрать аутентификацию для PHP:
http://pear.php.net/packages.php?catpid=1&catname=Authentication
Я думаю, что Basic или Digest Auth (+ https://SSL с самоподписанным сертификатом) будет хорошим выбором для вас Rest-Service (PHP RESTful JSON API).
В Android-приложении я считаю, что лучше всего выбрать библиотеку RestClient:
http://square.github.io/retrofit/
(Я рекомендую вам сохранить весь исходный код только на одном языке -Java. Вы можете легко создать службу Java Rest и добавить Spring Аутентификация безопасности)
Ответ 7
Сначала добавьте зависимости в сборку gradle (приложение)
реализация 'com.mcxiaoke.volley: library: 1.0.16' Затем следуйте приведенному ниже коду:
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);