2017-02-24 273 views
14

我是android开发的新手。我正在使用android studio开发应用程序。我所做的事情保护php api在android应用中的使用

  1. 创建一个DB两个表中它MySQL
  2. GETPOST方法创建了两个单独的api's
  3. 成功访问这两个api's

我有什么达到现在

  1. 能为GET数据形成GET api
  2. 能为POST数据使用POST api

我有什么做的,现在

我希望我的API在网上发布,也就是我想我的服务部署到服务器和访问这些文件。在这一点上,我能够在服务器上部署服务并访问它们。

现在我想要我的服务(api's)得到保护。为此我搜索了很多文章,并找到了两种方法。

  1. 使用yii框架。有人告诉我使用它,因为它自动保护了api's。但我不确定它是否确实。
  2. 手动固定api's

至于点1框架将是有益的,但它是新的给我,这将需要时间与它作为鸡舍我已经创建的Web服务。

对于点2我得到了一些信息

  1. using HMAC_SHA1
  2. DETECTING MOBILE DEVICES USING 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'] 
));} 

回声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从中我得到usernameID

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代码:(。如果有人能指导我或给我一个我遵循的教程,那将是非常有帮助的。

任何帮助将不胜感激。

回答

7

为了保护您的API,您需要一种机制来检测对api的请求是否来自可信来源。许多框架默认都带有这个功能。

但是你可以用JSON Web Tokens (jwt)用PHP授权添加到您的API请求

this page了解基于令牌的认证。

看看这个simple tutorial如何与智威汤逊确保您的PHP API端点。

如果您需要更高的安全性,则可能需要将OAuth提供程序服务添加到您的API。看看这篇文章how to write OAuth provider in PHP

3

唯一的方法来保护您的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的唯一ID(应该用复杂的变量名称改变)拒绝访问。例如:

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'; 
} 

而且在PHP否认如果不从机器人。

5 - 记录攻击者

你需要跟踪,如果有人是打破你的上述证券之一。 目前我使用ip-api.com来追踪攻击者。

你需要用mysql插入编写deny函数。 根据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步动态系统一样覆盖,那么很少有机会打破你的系统。
我还有一个要说的重要,如果您使用的是封闭的用户组,您应该使用请求 - >批准系统为每个用户首​​次使用其唯一ID进行应用程序注册,并轻松拒绝其他用户访问。

0

保护APIs以便被第三方访问是一个需要讨论的广阔领域。最常用的机制来保护API是基于令牌的访问控制。它可以以多种方式实施。

1您需要了解它的工作原理。请参阅此link和此link

然后试着看看如何实现它。

Working example of implementing 'Token Based Authentication' using 'JSON Web Token (i.e. JWT)' in PHP and MySQL?

如果您需要更深入的例子试试这个link为好。

如果您需要更多信息,请告诉我。

0

使用会话控制机制所有上述方法也都是一样的。用简单的话使用加密私钥来检测有效的源

0
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

您可以选择身份验证PHP这里:

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

我认为基本或摘要身份验证(+ https://开头带有自签名证书的SSL)将为您选择Rest-Service(PHP RESTful JSON API)。

对于Android应用我认为RESTClient实现库的最佳选择是:

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

(我建议你把所有的源代码在一个语言只有-Java您可以轻松创建Java Rest Service并添加春天。安全认证)