here - Asegurando php api para usar en aplicaciones de Android
here maps api javascript (7)
Soy novato en el desarrollo de Android. Estoy usando android studio
para desarrollar una aplicación. Cosas que he hecho
- Creé una base de
DB
con dos tablas enMySQL
. - Creó dos
api''s
separadas para los métodosGET
yPOST
. - Accedido exitosamente a los dos
api''s
Lo que he logrado por ahora.
- Capaz de obtener datos de la
api
GET. - Capaz de
POST
datos utilizando laapi
POST
Que tengo que hacer ahora
Quiero que mi API publique en línea, es decir, quiero implementar mis servicios en un servidor y acceder a ellos. En este punto, puedo implementar los servicios en el servidor y acceder a ellos.
Ahora quiero que mis servicios ( api''s
) estén asegurados. Para eso he buscado muchos artículos y he encontrado dos formas.
- Usa el framework
yii
. Alguien me dijo que lo usara porque automáticamente aseguraba lasapi''s
. Pero no sé a ciencia cierta si lo hace o no. - Asegure manualmente las
api''s
En cuanto al punto 1
el marco será útil, pero es nuevo para mí y llevará tiempo cooperar ya que ya estoy creado para los servicios web.
Para el punto 2
tengo alguna información.
- utilizando HMAC_SHA1
- Detección de dispositivos móviles usando PHP
Ambos enlaces parecen ser buenos, pero el enlace 1
no me da mucha información al respecto.
Obviamente quiero asegurar mis dos api''s
Ahora la parte del código
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;
Tengo una user class
de la que obtengo un username
y una ID
JSONfunctions.java
Esta clase es responsable de obtener datos de la 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
Esta clase es responsable del método 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("");
}
});
}
}
Como soy un novato, no sé qué hacer en el script php
y qué hacer en mi código de Android :(. Sería muy útil que alguien me guíe o me brinde un tutorial que siga.
Cualquier ayuda sería muy apreciada.
Asegurar las API para que un tercero pueda acceder a ellas es un vasto dominio que se discutirá. El mecanismo más utilizado para proteger las API es el control de acceso basado en token. Se puede implementar de muchas maneras.
Primero necesitas entender cómo funciona. Consulte este enlace y este link .
Luego trata de ver cómo implementarlo.
Si necesitas un ejemplo más detallado, prueba este enlace también.
Si necesitas más información avísame.
El único método para asegurar su api es hacer que su solicitud de Android sea única. Recopile datos más específicos de su aplicación.
1 - Obtener ID única de Android -
String UniqueID=Secure.getString(getActivity().getContentResolver(),Secure.ANDROID_ID);
Y pasarlo a través de tu api eg.
http://192.168.100.9:8000/MobileApp/GET_DATA.php?yourvalue=something&id=UniqueID
En tu php, deniega el acceso si no hay una ID única de Android (debería cambiar con un nombre de variable compleja) .Eg:
if($_REQUEST[''UniqueID'']=="" || strlen($_REQUEST[''UniqueID''])<9){ //do something about abuse }else{ //your code }
2 - Crea tu propia variable aleatoria en la aplicación de Android
Cree su propia variable para decidir si la solicitud proviene de su aplicación. Por ejemplo:
Random r = new Random();
int i1 = r.nextInt(9999 - 1000) + 1000;
Y también pase este valor a través de su solicitud y valide cuando se trata de php.
if($_REQUEST[''r'']>=1000 && $_REQUEST[''r'']<=9999){//}
Denegar solicitud si no pasa o valor incorrecto.
3 - Asegúrese de que las solicitudes provienen de Android
Quiero recomendar el uso de la mejor biblioteca php http://mobiledetect.net/ Compruebe si es de Android y escriba la función de denegación en los abusos no válidos.
4 - Validar la solicitud a través de la cadena User-Agent en PHP
$agent = $_SERVER[''HTTP_USER_AGENT''];
$agent=strtolower($agent);
if (strpos($agent, ''android'') !== false) {
$os = ''Android'';
}
Y negar si no es de android en php.
5 - Grabar los atacantes.
Debe hacer un seguimiento si alguien está rompiendo uno de sus valores anteriores. Actualmente estoy usando ip-api.com para rastrear a los atacantes.
necesitas escribir la función de negar con mysql insert. de acuerdo con ip-api, obtendrá
1- ip de los atacantes
2- La geolocalización de los atacantes.
3- ISP de los atacantes
Así que puedes negarlos estáticamente.
Está a punto de usar de forma segura su api desde Android y casi se le niegan las solicitudes de PC. Pero tres es una oportunidad para romper su aplicación con ingeniería inversa como dex2jar o ShowJava y obtener su estructura de datos simple. Como programador, las funciones y códigos anteriores son muy fáciles para ellos y entrarán con entradas de datos falsos.
Por lo tanto, no debe escribir un programa con valores estáticos, un enlace tan importante " http://192.168.100.9:8000/MobileApp/GET_DATA.php " con el código codificado como en su aplicación. Debe dividir los datos, simplemente cifrar y obtener todas las direcciones URL principales de forma dinámica, como se ha indicado anteriormente en el método phi / mysql api.
Si cubrió un sistema dinámico de 2 pasos, hay muy pocas posibilidades de interrumpir su sistema.
Tengo una cosa importante que decir, si está utilizando para un grupo cerrado de usuarios, debe usar el sistema de solicitud-> aprobar para cada usuario para el registro de aplicaciones por primera vez utilizando su ID única y negar fácilmente el acceso de los demás.
Para proteger sus API, necesita un mecanismo para detectar que la solicitud a la api se realiza desde una fuente confiable. Muchos marcos vienen con esta característica por defecto.
Sin embargo, solo puede usar JSON Web Tokens (jwt) con PHP para agregar autorización a sus solicitudes de API.
Aprenda sobre la autenticación basada en token de esta página .
Echa un vistazo a este sencillo tutorial sobre cómo asegurar tus puntos finales de PHP con JWT.
Si necesita aún más seguridad, es posible que desee agregar el servicio del proveedor OAuth a su API. Echa un vistazo a esta publicación sobre cómo escribir proveedor OAuth en PHP
Primero agregue las dependencias en build gradle (aplicación)
implementación ''com.mcxiaoke.volley: library: 1.0.16'' Luego siga el siguiente código:
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);
Puedes elegir tu autenticación para PHP aquí:
http://pear.php.net/packages.php?catpid=1&catname=Authentication
Creo que la Autenticación Básica o Digestiva (+ https: // SSL con certificado autofirmado) será una buena opción para usted Rest-Service (PHP RESTful JSON API).
Para la aplicación de Android, creo que la mejor opción para la biblioteca RestClient es:
http://square.github.io/retrofit/
(Te recomiendo que guardes todo el código fuente en un solo idioma, Java. Puedes crear fácilmente el Servicio Java Rest y agregar la autenticación de seguridad Spring)
Utilice el mecanismo de control de sesión. Todos los métodos anteriores también están hablando por el mismo. En palabras simples use una clave privada encriptada para detectar la fuente válida
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