简体   繁体   English

保护 php api 以在 android 应用程序中使用

[英]Securing php api to use in android application

I am newbie to android development.我是android开发的新手。 I am using android studio for developing an application.我正在使用android studio开发应用程序。 Things i have done我做过的事

  1. Created a DB with two tables in it in MySQL .创建一个DB带有两个表中MySQL
  2. Created two separate api's for both GET and POST methods.GETPOST方法创建了两个单独的api's
  3. Successfully accessed both api's成功访问了两个api's

What i have achieved for now我现在取得的成就

  1. Able to GET data form the GET api .能够从 GET api GET数据。
  2. Able to POST data using the POST api能够使用 POST api POST数据

What i have to do now我现在必须做什么

I want my api to publish online, ie I want to deploy my services into a server and access them.我希望我的 api 在线发布,即我想将我的服务部署到服务器并访问它们。 At this point i am able to deploy the services on the server and accessed them.此时,我能够在服务器上部署服务并访问它们。

Now i want my services( api's ) to be secured.现在我希望我的服务( api's )得到保护。 For that i have searched many articles and found two ways.为此,我搜索了许多文章并找到了两种方法。

  1. Use yii framework.使用yii框架。 Someone told me to use it because it automatically secured the api's .有人告诉我使用它,因为它会自动保护api's . But i don't know for sure whether it do or not.但我不确定它是否可以。
  2. Manually secure the api's手动保护api's

As for point 1 the framework will be helpful but it's new to me and it will take time to coop with it as i am already created the web services.至于第1点,该框架会有所帮助,但它对我来说是新的,因为我已经创建了 Web 服务,所以需要时间来配合它。

For point 2 i got some information对于第2点,我得到了一些信息

  1. using HMAC_SHA1使用 HMAC_SHA1
  2. DETECTING MOBILE DEVICES USING PHP 使用 PHP 检测移动设备

Both links seems to be good but link 1 doesn't gives me much info on that.两个链接似乎都不错,但链接1没有提供太多相关信息。

Obviously i want to secure my both api's显然我想保护我的两个api's

Now the code part现在是代码部分

GET_DATA.php 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)); echo json_encode(array('users'=>$result));

POST_DATA.php 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;

I have a user class from which i am getting username and ID我有一个user class ,我从中获取usernameID

JSONfunctions.java JSONfunctions.java

This class is responsible for getting data from the api这个类负责从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 PutUtility.Java

This class is responsible for POST method这个类负责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主活动.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("");
            }
        });
    }


}

As i am newbie, so i don't know what to do in php script and what to do in my android code :(. It would be very helpful if anyone can guide me or give me a tutorial that i follow.因为我是新手,所以我不知道在php脚本中该做什么以及在我的 android 代码中做什么:(。如果有人可以指导我或给我一个我遵循的教程,那将非常有帮助。

Any help would be highly appreciated.任何帮助将不胜感激。

To secure your APIs, you need a mechanism to detect that the request to the api is made from a trusted source.为了保护您的 API,您需要一种机制来检测对 api 的请求是否来自受信任的来源。 Many frameworks come with this feature by default.默认情况下,许多框架都带有此功能。

However you can just use JSON Web Tokens (jwt) with PHP to add authorization to your api requests但是,您可以将JSON Web Tokens (jwt)与 PHP 结合使用来为您的 api 请求添加授权

Learn about token based authentication from this page .从此页面了解基于令牌的身份验证。

Check out this simple tutorial on how to secure your PHP api endpoints with JWT.查看这个简单的教程,了解如何使用 JWT 保护您的 PHP api 端点。

If you need even more security you might want to add OAuth provider service to your API.如果您需要更高的安全性,您可能希望将 OAuth 提供程序服务添加到您的 API。 check out this post on how to write OAuth provider in PHP查看这篇关于如何在 PHP 中编写 OAuth 提供程序的帖子

The only method to secure your api is making your android request to be unique .Collect more specific data from your app.保护您的 api 的唯一方法是使您的 android 请求独一无二。从您的应用程序中收集更具体的数据。

1 - Get Android Unique ID - 1 - 获取 Android 唯一 ID -

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

And pass it through your api Eg .并通过您的 api 例如传递它。

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

In your php, deny access if there is no Android Unique ID(should change with complex variable name).Eg :在您的 php 中,如果没有 Android 唯一 ID(应更改为复杂的变量名称),则拒绝访问。例如:

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

2 - Create your own random variable in Android App 2 - 在 Android 应用程序中创建您自己的随机变量

Create your own variable to decide to make sure the request comes from your app Eg:创建您自己的变量以决定确保请求来自您的应用程序,例如:

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

And also pass this value via your request and validate when it comes to php .并且还通过您的请求传递此值并在涉及 php 时进行验证。

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

Deny request if not passing or wrong value.如果未通过或错误值,则拒绝请求。

3 - Make sure requests come from Android 3 - 确保请求来自 Android

I want to recommend to use free best php library http://mobiledetect.net/ Check whether it is from android and write deny function on invalid abuses.我想推荐使用免费的最好的 php 库http://mobiledetect.net/检查它是否来自 android 并在无效滥用时编写拒绝功能。

4 - Validate request via User-Agent string in PHP 4 - 通过 PHP 中的 User-Agent 字符串验证请求

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

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

And deny if not from android in php.如果不是来自 php 中的 android,则拒绝。

5 - Record the attackers 5 - 记录攻击者

You need to track if someone is breaking one of your above securities.您需要跟踪是否有人破坏了您的上述证券之一。 Currently I am using ip-api.com to track attackers.目前我正在使用ip-api.com来跟踪攻击者。

you need to write deny function with mysql insert.您需要使用 mysql insert 编写拒绝函数。 according to ip-api, you will get根据ip-api,你会得到

1- Attackers' ip 1-攻击者的ip
2- Attackers' geolocation 2- 攻击者的地理位置
3- Attackers' ISP 3- 攻击者的 ISP

So you can deny them statically.所以你可以静态地拒绝它们。

It is about to safe to use your api from android and almost denied pc requests.从 android 使用您的 api 即将安全,并且几乎拒绝了 pc 请求。 But three is a chance to break your app with reverse engineering like dex2jar or ShowJava and grab your simple data structure.但是三是一个机会,可以使用 dex2jar 或 ShowJava 之类的逆向工程来破坏您的应用程序并获取您的简单数据结构。 As a programmer, above functions and codes are very easy for them and they will get in with fake data inputs.作为一个程序员,上面的函数和代码对他们来说很容易,他们会得到假数据输入。

So you should not write a program with static values, such important link " http://192.168.100.9:8000/MobileApp/GET_DATA.php " as hard coded as in your app.所以你不应该写一个带有静态值的程序,像在你的应用程序中那样硬编码的重要链接“ http://192.168.100.9:8000/MobileApp/GET_DATA.php ”。 You should split data,simple encrypt and get all of your main urls dynamically as above secured php/mysql api method.您应该拆分数据,简单加密并动态获取所有主要网址,如上述安全的 php/mysql api 方法。

If you covered just like 2 step dynamic system, there is very very few chances to break in your system.如果您像 2 步动态系统一样覆盖,那么您的系统崩溃的机会非常少。
I've one important left to say, if you are using for closed group of users , you should use request->approve system for each user for first time app registration by using their unique ID and easily deny access from the others.我还有一个重要的事情要说,如果您使用的是封闭的用户组,您应该使用请求-> 批准系统为每个用户首​​次使用他们的唯一 ID 注册应用程序,并轻松拒绝其他人的访问。

You can choose you Authentication for PHP here:您可以在此处选择 PHP 身份验证:

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

I think that Basic or Digest Auth (+ https:// SSL with self signed certificate) will be good choose for you Rest-Service (PHP RESTful JSON API).我认为 Basic 或 Digest Auth(+ https://带有自签名证书的 SSL)将是您 Rest-Service(PHP RESTful JSON API)的不错选择。

For Android application I think the best choose for RestClient library is:对于 Android 应用程序,我认为 RestClient 库的最佳选择是:

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

(I recommend you to keep all source code in one Language only -Java. You can easy create Java Rest Service and add Spring Security Authentication) (我建议您将所有源代码仅使用一种语言 - Java。您可以轻松创建Java Rest Service并添加 Spring Security 身份验证)

secure the APIs in order to be accessed by a 3rd party is a vast domain to be discussed.保护 API 以供第 3 方访问是一个需要讨论的广阔领域。 Most used mechanism to secure APIs is token based access control.最常用的保护 API 的机制是基于令牌的访问控制。 It can be implemented in many ways.它可以通过多种方式实现。

1st you need understand how it works. 1st 你需要了解它是如何工作的。 Refer this link and this link .请参阅此链接和此链接

Then try to look at how to implement it.然后试着看看如何实现它。

Working example of implementing 'Token Based Authentication' using 'JSON Web Token (ie JWT)' in PHP and MySQL? 在 PHP 和 MySQL 中使用“JSON Web 令牌(即 JWT)”实现“基于令牌的身份验证”的工作示例?

If you need more in-depth example try this link as well.如果您需要更深入的示例,也可以尝试此链接

If you need more information let me know.如果您需要更多信息,请告诉我。

Use Session control mechanism all the above methods are also talking for the same.使用Session控制机制上述所有方法也都是一样的。 In Simple words use encrypted private key to detect the valid source简而言之,使用加密的私钥来检测有效来源

First add the dependencies in build gradle (app)首先在build gradle(app)中添加依赖
implementation 'com.mcxiaoke.volley:library:1.0.16' Then follow the below code:实现 '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);

I will simply say, If you already using PHP OPP, then no need to go with any framework.我会简单地说,如果您已经在使用 PHP OPP,那么无需使用任何框架。 It will be time consuming for you.这对你来说会很费时间。 Solution is: "Use remember_token system as like laravel and yii. Authenticate to each method before filter."解决方案是:“像laravel和yii一样使用remember_token系统。过滤之前对每个方法进行身份验证。” If you are using Core PHP.如果您使用的是核心 PHP。 Try same code and include it before filter each method in your api尝试相同的代码并在过滤 api 中的每个方法之前包含它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM