Java 安卓应用程序从服务器检索数据,但要安全

Java 安卓应用程序从服务器检索数据,但要安全,java,android,inputstream,bufferedreader,Java,Android,Inputstream,Bufferedreader,显然,我不是安卓或java专家。我想在Android应用程序中做的是,从服务器加载数据。我已经开始工作这部分和源代码是附加的。但我想用一种安全的方式来做。作为第一步,而不是http://thisismyurl.com/a.php?action=get我想用用户名/密码这样做:http://username:password@thismyurl.com/a.php?action=get我该怎么做?我是否应该将用户名和密码部分添加到url 假设我已经做到了这一点,这将没有任何用处,因为有人可以打开a

显然,我不是安卓或java专家。我想在Android应用程序中做的是,从服务器加载数据。我已经开始工作这部分和源代码是附加的。但我想用一种安全的方式来做。作为第一步,而不是
http://thisismyurl.com/a.php?action=get
我想用用户名/密码这样做:
http://username:password@thismyurl.com/a.php?action=get
我该怎么做?我是否应该将用户名和密码部分添加到url

假设我已经做到了这一点,这将没有任何用处,因为有人可以打开apk并反编译源代码,然后获取url和用户名/密码。那么,有没有一种真正安全的方法可以做到这一点

我希望我在这里得到理解

String url = "http://thisismyurl.com/a.php?action=get";
String result = Web.executeWeb(url);

public class Web {

    public static String executeWeb(final String url) {

        final StringBuilder sb = new StringBuilder();

        Thread thread = new Thread(new Runnable() {
            public void run() 
                {
                try 
                {
                    InputStream is = (InputStream) new URL(url).getContent();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    String result, line = reader.readLine();
                    result = line;
                    while((line=reader.readLine())!=null){
                        result+=line;
                    }

                    sb.append(result);
                    //System.out.println(result);       
                    //Log.i("My Response :: ", result);

                } catch (Exception e)
                {
                // TODO: handle exception
                }
            }
          });   

        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return sb.toString();

    }   

}

我所做的是,我使用AES加密。每当用户注册时,我都会向应用程序发送头中的加密密钥和版本,以便所有通信都将被加密。服务器始终检查密钥的版本,然后相应地解密。如果新密钥可用,服务器将向应用程序发送新密钥,然后应用程序更新密钥,然后使用该密钥解密

我使用这些方法在android中解密和加密

   public  byte[] decrypt(byte[] cipherText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance(cipherTransformation);
    SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
    cipherText = cipher.doFinal(cipherText);
    return cipherText;
}

public byte[] encrypt(byte[] plainText, byte[] key, byte [] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance(cipherTransformation);
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    plainText = cipher.doFinal(plainText);
    return plainText;
}
并在请求中添加标题,如

request.addHeader("KeyVersion",String.valueOf(utils.getInt(Key.Key_Version)));
    request.addHeader("EmpId",String.valueOf(utils.getInt(Key.Emp_Id)));
当收到回复时,我会检查新的钥匙,比如

Header[] headers = response.getHeaders("KeyVersion");  

    if(headers.length>0){
        String keyVersion = headers[0].getValue();
        if (keyVersion == null) {
            System.out.println("Key 'Server' is not found!");
        } else {
                System.out.println("Key 'Server' found! -- with version "+keyVersion);
                if(utils.getInt("KeyVersion")<Integer.parseInt(keyVersion)){
                    utils.saveInt("KeyVersion", Integer.parseInt(keyVersion));
                    utils.saveString("Key", response.getHeaders("KeyValue")[0].getValue());
                    String s = response.getHeaders("KeyValue")[0].getValue();
                    System.out.println("key is "+s);
                }
        }
Header[]headers=response.getHeaders(“KeyVersion”);
如果(标题长度>0){
字符串keyVersion=headers[0]。getValue();
if(keyVersion==null){
System.out.println(“找不到“服务器”键!”);
}否则{
System.out.println(“找到了密钥‘服务器’——版本为“+keyVersion”);

如果(utils.getInt(“KeyVersion”)首先,不要使用密码本身,只能使用密码的哈希表示(sha1函数)。其次,可以使用SSL(https)建立安全连接。
总而言之,用户单击登录按钮后,从edittext获取密码并创建其哈希。在服务器端也使用哈希表示法。接下来,将数据作为https请求主体发送到www.yoursite.com/login,请求主体中将是您的数据。将其作为json f.e.发送。

加密不是答案。

如果有人想要存储在客户端中的URL、用户和密码,你无法避免。即使它是加密的,你也必须向客户端提供解密密钥,然后客户端可以自行反编译

您无法阻止服务接口的反向工程。

因此无法阻止其他客户端使用您的服务接口。使用SSL嗅探网络流量很容易。即使SSL也没有问题,因为我们可以在数据加密之前操纵客户端本身


首先,你应该首先考虑你想要达到的目标,以及如何以及之后决定你需要什么。 首先,你必须清楚,恶意用户会试图破解你的应用程序,如果你的应用程序存储了财务、个人或其他敏感数据,持久性将明显增加

尽管如此,仍需考虑以下几点:

  • 将密钥硬编码到代码中是个坏主意。如果你这样做,破解者破译你使用的密钥只是时间问题

  • 在URL中硬编码密钥甚至是一个更糟糕的主意。请记住,在到达终点(您的服务器)之前,您的URL将经过许多地方,同时,任何访问该流量的人都将看到您的凭据,即使您不加密地发送这些凭据,也无需付出任何努力

  • 根据您将如何生成密钥,我建议使用对称或非对称加密:

    • 如果您计划为所有客户端存储唯一密码(顺便说一句,这也是一个坏主意,因为如果恶意用户破坏了您的密钥,他们可能拥有all您客户端的信息),您可以使用类似AES的对称加密方法。您只需加密消息,通过
      HTTP POST
      (例如)并在另一边解密。这是一个非常简单的概念

    • 如果您计划为每个客户机生成一个密钥,那么您还有一个额外的障碍,您需要让服务器知道您生成的密钥,或者让客户机知道为客户机生成的密钥(取决于您如何面对它)。在这种情况下,您可以使用下一点方法(这基本上是我从所有这些建议中推荐的一个)

  • 您可以简单地使用非对称加密方法。这意味着服务器生成一对密钥,一个公共密钥,一个私有密钥。用户(客户端)将使用公共密钥加密邮件并将其发送到服务器。您可能想知道:我如何保护我的邮件,以便除了我的服务器之外没有人可以解密它们?这就是私钥加入的地方,如果您拥有私钥,您可以解密邮件。这就是为什么您不想与任何人共享它(这就是它的名字的来源)。这样,你的客户端可以随时拥有你的公钥,而不需要任何混淆,然后你用它来加密一些文本并发送它。服务器将使用它的私钥解密消息并相应地处理它

最后一种方法的优点是:

  • 您不必担心如何使您的密钥安全地到达另一方,因为它将被加密,只有服务器能够解密

  • 您不需要为每个客户机生成密钥

  • 如果您选择了一个好的非对称算法,比如SSL/TLS,那么您就不必担心它会被破解(或者至少不必像选择其他方法那样担心)

  • 替换一对旧密钥非常容易,例如生成一对新密钥,替换旧私钥,并使您的客户机拥有新的公钥

<
Header[] headers = response.getHeaders("KeyVersion");  

    if(headers.length>0){
        String keyVersion = headers[0].getValue();
        if (keyVersion == null) {
            System.out.println("Key 'Server' is not found!");
        } else {
                System.out.println("Key 'Server' found! -- with version "+keyVersion);
                if(utils.getInt("KeyVersion")<Integer.parseInt(keyVersion)){
                    utils.saveInt("KeyVersion", Integer.parseInt(keyVersion));
                    utils.saveString("Key", response.getHeaders("KeyValue")[0].getValue());
                    String s = response.getHeaders("KeyValue")[0].getValue();
                    System.out.println("key is "+s);
                }
        }