使用 json (android) 保护 http 请求

Posted

技术标签:

【中文标题】使用 json (android) 保护 http 请求【英文标题】:protect http request using json (android) 【发布时间】:2013-04-06 04:31:45 【问题描述】:

我正在使用 json 请求登录并显示与用户有关的消息。但如果我从浏览器发出相同的请求,它仍然可以工作。我正在为我的 App 使用 php-mysql。 我没有任何网站,所以我需要应用程序本身的答案。

我正在使用带有 android 应用程序的 facebook sdk,所以我没有任何密码。我想在调用时保护用户和用户数据配置文件之间的聊天消息。就是这样。

我的问题是:

    如何确保仅在应用内拨打电话?

    当某些人试图在浏览器中复制和粘贴代码时,我如何确保通话安全?

3.10秒后创建的消息有超时。所以不能重复使用相同的url和msg。

我有 http://example.com/login=emailId 之类的 http 调用;

获取消息:http://example.com/getMsgs/user=uiniqueNo;

我已经提供了我在应用程序中使用的上述链接,它工作正常但不安全。 请向我推荐一些文件和流程。我已经检查了这个链接Protect HTTP request from being called by others,但不清楚。请向我推荐任何具有上述要求的教程。提前致谢。非常感谢您的帮助。

public class CustomizedListView extends Activity 
    // All static variables
    static final String URL = "http://example.com/getmsgs/userno=123";
    // XML node keys
    static final String KEY_SONG = "song"; // parent node
    static final String KEY_ID = "id";
    static final String KEY_TITLE = "title";
    static final String KEY_ARTIST = "artist";
    static final String KEY_DURATION = "duration";
    static final String KEY_THUMB_URL = "thumb_url";

    ListView list;
    LazyAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();

        JSONObject json = JSONfunctions.getJSONfromURL(URL);


        try 
            JSONObject arr2 = json.getJSONObject("feed");
            JSONArray arr = arr2.getJSONArray("entry");

            for (int i = 0; i < arr.length(); i++) 
                JSONObject e1 = arr.getJSONObject(i);

                JSONArray arr3 = e1.getJSONArray("im:image");

                JSONObject arr8 = e1.getJSONObject("im:name");

                JSONObject arr10 = e1.getJSONObject("im:artist");

                    JSONObject e12 = arr3.getJSONObject(0);

            // creating new HashMap
            HashMap<String, String> map = new HashMap<String, String>();

            map.put(KEY_THUMB_URL,  e12.getString("label"));

            map.put(KEY_ARTIST, arr8.getString("label"));
            map.put(KEY_TITLE, arr10.getString("label"));
            // adding HashList to ArrayList
            songsList.add(map);
            

         catch (JSONException e) 
            // Log.e("log_tag", "Error parsing data "+e.toString());
            Toast.makeText(getBaseContext(),
                    "Network communication error!", 5).show();
        


        list=(ListView)findViewById(R.id.list);

        // Getting adapter by passing xml data ArrayList
        adapter=new LazyAdapter(this, songsList);        
        list.setAdapter(adapter);

        // Click event for single list row
        list.setOnItemClickListener(new OnItemClickListener() 

            @SuppressWarnings("unchecked")
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) 


                HashMap<String, String> o = (HashMap<String, String>) list.getItemAtPosition(position);
                Toast.makeText(CustomizedListView.this, "ID '" + o.get("KEY_TITLE") + "' was clicked.", Toast.LENGTH_SHORT).show(); 

            
        );     
       

在上面的代码中,任何人都可以猜到 usersno,但是我如何确保应用程序和 php 服务器中没有 123。所以即使使用嗅探器程序并进行逆向工程以从 apk 文件中获取代码,数据仍然是保护和加密应该深入操作系统,用户无法破解,因此我可以解密服务器 php 中的代码,用户将无法随机键入任何内容为 123。

<?php

$strno=$_GET['strno'];

if (isset($strno))

        $connect=mysql_connect("localhost","test","test") or die ('Connection error!!!');
        mysql_select_db("test") or die ('Database error!!!');

    $query=mysql_query("select sno FROM users  where strno='$strno';");
    while($row = mysql_fetch_assoc($query))

    
        $jsonoutput='"json":
            "msg_sub":"'.$row['msg_sub'].'",
            ';
    



echo trim($jsonoutput);
mysql_close($connect) or die ('Unable to close connection-error!!!');


?>

【问题讨论】:

我注意到你有 http://example.com/getmsgs/limit=20/userno=123 作为你的 api 端点。你能发布在那里运行的代码吗? 我在上面。现在随时发布。 也添加了 php 代码。它的简化。 【参考方案1】:

好吧,没有方式可以真正完美地保护这个系统,除非你使用 https 在你的 api 和你的 js 客户端之间传输数据。

这就是你要做的:

    首先在你的数据库端创建一个用户登录系统,用户名/密码表 接下来创建一个表单供用户登录 每当用户尝试访问 api 时,您的服务器将检查它是否为该用户设置了会话,他们要么必须登录,要么传递现有的会话 ID,这将授予他们访问权限 接下来是购买 https 证书,以确保您的数据安全传输 现在在对 api 的每个请求中,服务器总是检查他们的用户是否发送了有效的 SESSION ID,如果没有,它会将他们简单地重定向到登录页面

这几乎是您为系统添加安全性的唯一方法。最重要的部分是 https 证书。没有这个,无论用户/密码有多好,它仍然可能受到损害。

编辑

这里有一些示例代码可以帮助您入门。此代码未经测试,只是为了给您一个想法。您可以阅读有关会话的所有信息here。

 <?php

    /*
        like I said earlier, you need to have a "login" screen on your app
        - when the user clicks login it POSTS the request back here
    */

    if(isset($_SESSION['username']))
        //the username is in the session so it means
        //theyre already logged in
        //not sure what strno is doing but you can do that here

        $strno=$_GET['strno'];

        if (isset($strno))
        
                $connect=mysql_connect("localhost","test","test") or die ('Connection error!!!');
                mysql_select_db("test") or die ('Database error!!!');

            $query=mysql_query("select sno FROM users  where strno='$strno';");
            while($row = mysql_fetch_assoc($query))

            
                $jsonoutput='"json":
                    "msg_sub":"'.$row['msg_sub'].'",
                    ';
            

        

        echo trim($jsonoutput);
        mysql_close($connect) or die ('Unable to close connection-error!!!');

    else if(isset($_POST) && isset($_POST['username']) && isset($_POST['password']))
        //log them in
        //query ur database to see if the user exists
        //if you get a row back then store that row in the session like
        //note: this is just example code

        if(/*user is in database, get the row....*/)
            session_start();
            $_SESSION['username'] = $row['username'];
        
    else
        die("Access Denied");
    

?>

【讨论】:

感谢您的回复先生。但我需要它关于应用程序本身,因为我没有相同的网站。另外我没有使用会话 ID。我也没有为用户登录声明请您提供链接,该链接将为您建议的解释提供示例/示例。我非常感谢您的帮助。再次感谢先生。 我也更新了问题,因为我正在使用 facebook sdk 登录我的应用程序。 好吧,让事情变得非常简单,如果您尝试访问 http:/example.com/getMsgs/user=uiniqueNo 但您无权访问 api,您不应该知道 uniqueNo 是什么。因此,如果您在不知道uniqueNo 是什么的情况下发出请求,它应该重定向您的登录页面。登录后,session_start() 被调用,这将为该用户创建一个唯一的 session_id。下次用户尝试访问 api 时,他们需要在请求中传递他们的 session_id。服务器将执行session_start() 以恢复会话,从而授予对应用程序的访问权限。 您好,先生,我正在使用 android 应用程序是否可以解决会话 id 部分的问题,因为它适用于应用程序,上面的描述适用于 html。请您在 android 调用中提出类似的建议。 编辑你的问题以包含更多的android代码,如果我能看到你的代码,我可能会更好地帮助你。【参考方案2】:

有两种方法可以实现这一目标。首先是使用GET 方法,您可以在您正在寻找的服务器端创建一个特定的参数。例如,从您的 android 应用程序中,您发送 http://www.my-backend.com/api/test_api?my_secure_code=thisIsTestString 并且服务器返回正确的响应,但如果您发送 http://www.my-backend.com/api/test_api?my_secure_code=thatsAnotherString ,则您在请求中搜索的参数值不是 thisIsTestString,因此您应该返回错误消息。

在我看来,第二种方法更好,因为在我看来使用GET 并不安全。它比使用POST 更容易。在这种情况下,您必须将 my_secure_param 作为 post 参数发送,您可以通过在浏览器中键入来使用它(仍然有一种方法可以通过浏览器安装用于 post 请求的插件来实现此目的)。所以我认为这里最好的解决方案是使用POST 请求,同时连接到后端使用MD5SHA1 发送一些散列字符串(至少这是我们保护与服务器连接的方式+一些额外的东西) .

编辑:关于 cmets,您可以通过在您的服务器上为特定用户创建某种标识来实现此目的,而不是信任 facebook。这只是一个建议...例如,您可以从 facebook 获取 id 用户并创建一个唯一的哈希 id,您将其存储在您的服务器中,并且每次您从应用程序发送请求时,您都必须发送该唯一 id,这将在应用程序中创建的方式与在服务器上创建它的方式相同。如果匹配,则每次有人发送消息时,您都必须检查该哈希值,如果不只是返回错误..别忘了,使用POST请求而不是GET!如果不更改服务器后端中的一些代码,就无法实现这样的目标。

【讨论】:

感谢您的回复先生。但我需要它关于应用程序本身,因为我没有相同的网站。请您提供链接以提供示例/示例来解释您建议。我非常感谢您的帮助。再次感谢先生。 我也更新了问题,因为我正在使用 facebook sdk 登录我的应用程序。 您是否使用其他服务器向用户传递消息? 是的,服务器存储与应用程序而不是 Facebook 相关的个人消息,所以我如何确保从浏览器发送和查看其他用户的消息,因为唯一的用户 ID 可能会通过反复试验猜到。跨度> 为了保护来自嗅探器的连接,您可以使用网络证书,并且您应该在您的 android 应用程序中处理信任方法。关于android端的逆向工程,使用proguard混淆你的代码,它是在android中构建的,所以你不会有问题。

以上是关于使用 json (android) 保护 http 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何保护与 Android 应用程序交互的 PHP JSON api 端点?

如何在 Android 中打印受 Auth0-JWT 保护的私有 API 端点 JSON 对象?

如何在 .NET WCF 中保护 HTTP JSON Web 服务

使用简单令牌保护 REST 服务

Android:SearchBox -> 使用通过 HTTP/JSON 接收的数据动态填充提示列表

将json对象发送到android中的HTTP服务器