如何在Android应用程序中隐藏API的URL和参数?

11

我很好奇,如果没有商业产品进行混淆,是否有办法安全地存储API url和参数,使其无法在逆向工程中被编译?我尝试了所有我的应用程序,它们的API url和代码都很容易阅读。 我非常担心安全问题。


嘿,@Chirag,找到解决方案了吗? - Darth Vader
1
@Abhishekkumar,我没有找到任何适当的解决方案,只是从API端进行了更多的安全性设置,并在buildconfig文件中定义了URL。 - Chirag Joshi
仅供示例...API提供了哪些安全性保障? - Darth Vader
你找到任何解决方案了吗?我正在寻找相同的东西。我通过API调用将机密令牌传递给远程服务器,即使混淆后,我发现它在我的.class文件中暴露出来。 - Aniket Velhankar
3个回答

12

将Url隐藏在环境变量、BuildConfig和Android Studio中

一个简单的避免不良实践的方法是将值存储在环境变量内,这样只有您的机器知道它,然后以某种方式读取这些值并在构建时将其注入到代码中。让我们看看如何使用Android Studio、Gradle和BuildConfig来完成此操作。

首先,我们需要创建这些环境变量。在Linux和Mac中,请创建或编辑文件~/.gradle/gradle.properties(注意实际的Gradle用户主目录位置)并添加一些值:

WEBServiceBaseURL="http://192.168.2.102:2323/"
WEBServiceBaseSMSURL="https://www.example.com/"

输入图片说明

其次,在您的模块的 build.gradle 文件中添加以下行

//Add these lines
def Base_URL = '"' + WEBServiceBaseURL + '"' ?: '"Define BASE URL"';
def SMS_Base_URL = '"' + WEBServiceBaseSMSURL + '"' ?: '"Define SMS BASE URL"';

android.buildTypes.each { type ->
    type.buildConfigField 'String', 'Base_URL', WEBServiceBaseURL
    type.buildConfigField 'String', 'SMS_Base_URL', WEBServiceBaseSMSURL
}

在此输入图片描述

在Java文件中使用

BuildConfig.Base_URL会返回URL字符串

  public static Retrofit getClient() {
        if (retrofit==null) {
            retrofit =new Retrofit.Builder()
                    .baseUrl(BuildConfig.Base_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

6
你的想法无法隐藏URL。 - Sagar Zala
7
反编译时易于查找 - Erfan
@erfan 有其他的方法可以实现同样的功能吗? - Arbaz.in
2
在反编译应用程序后很容易看到。 - Rohit Suthar
这可以通过反向工程非常容易地提取出来。将URL移动到本地代码或应用加密可以实现您的目标。 - Amir Raza
显示剩余5条评论

6

我找到了一种解决方案,可以使用NDK隐藏基本URL以保持API的安全性。将Base64编码的字符串放在cpp文件中,并从Java类中调用它并解码Base64。

将C++(NDK)支持添加到您的项目中。您可以将其包含到新项目或旧项目中。

您的CPP文件名称可以是(native-lib.cpp)

在线搜索Base64编码器并对您的基本URL进行编码。现在将编码后的字符串保留在cpp文件内

示例代码如下:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_touhidapps_MyProject_utils_MyConstants_baseUrlFromJNI(JNIEnv *env, jobject) {
    std::string mUrl = "aHR0cDovL2FwaS5leGFtcGxlLmNvbS8="; //"http://api.example.com/";
    return env->NewStringUTF(mUrl.c_str());
}

在MyConstants.java类中:(我将所有API网址都保存在这里。)

// load c++ library
static {
    System.loadLibrary("native-lib");
}

public static native String baseUrlFromJNI();

// decode base64 to a string and get normal url
public static String getSecureBaseUrl() {
    String mUrl = baseUrlFromJNI();
    try {
        String text = new String(Base64.decode(mUrl, Base64.DEFAULT), "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    
    mUrl = "http://demo.example.com/"; // don't change this link. This will not execute normally, if exception happens then it will return a demo url.
    return mUrl;
}

现在您可以像下面这样获取原始url:

public static final String API_BASE = "" + getSecureBaseUrl();

1
@ShivamSharma 我不这么认为。 - Xihuny
mUrl = "http://demo.example.com/"; 这是Java文件中的一行代码,因此同样可以进行提取。 - Ali Ahmed
@AliAhmed 不要更改此链接。如果发生异常,它将返回演示网址并防止应用程序崩溃。URL更改在cpp文件内部。 - Touhid
@Touhid,你在Notepad++中的.os文件中找到URL了吗? - karan
@karen 不是的。Notepad++仅支持Windows系统。如果我有一台Windows电脑,我可以测试一下。 - Touhid
显示剩余4条评论

3

您的问题不适合在StackOverflow上讨论,因为主题太广泛且主要基于个人意见。但是,我想作为答案在这里分享一些我的想法。

使用代码混淆隐藏API URL绝对是一个好主意,并且在某些情况下可能有效。您还可以考虑在代码中加密API URL并将加密后的URL存储在SharedPreferences或本地存储中,每次使用API URL调用Web服务时需要再次解密。

但是,这些方法都不能确保您的API URL无法破解。如果有人真的想获取您的API URL,则可以通过跟踪您用于调用Web服务的网络轻松获取这些内容。

因此,在大多数情况下,加密API URL和混淆变量名称以隐藏API URL将不起作用。是的,我也没有看到获取API URL会有任何安全漏洞。因为API服务器应该设计成可以阻止攻击者通过API进行的非法服务调用。您可以考虑在主机机器上设置防火墙或设置基本身份验证协议来保护数据。有很多方法可以防止这些安全漏洞活动。您还可以考虑阅读这篇文章,我发现它对了解如何保护API免受滥用很有帮助。

希望这可以帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接