![](/img/trans.png)
[英]Easiest secure way to exchange data from Perl scripts to Java Android App
[英]Android App Retrieve Data from Server but in a Secure way
显然我不是android或java专家。 我要在Android应用程序中执行的操作是从服务器加载数据。 我已经开始处理此部分,并附带了源代码。 但是我想以一种安全的方式来做。 第一步,不是使用http://thisismyurl.com/a.php?action=get
,而是要使用用户名/密码,例如: http://username:password@thisismyurl.com/a.php?action=get
我将如何做? 我应该只将用户名和密码部分添加到网址中吗?
可以说我已经实现了这一点,因为有人可以打开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();
}
}
首先,您应该首先考虑要实现的目标以及如何以及随后确定需要的目标。
首先,您必须清楚恶意用户将尝试破解您的应用程序,并且如果您的应用程序存储财务,个人或其他类型的敏感数据,则持久性将呈指数级增长。
话虽这么说,但有几点注意事项:
将密钥硬编码到代码中是个坏主意。 如果这样做,那么解密者破译使用的密钥只是时间问题。
对URL中的键进行硬编码甚至是一个更糟糕的主意。 请记住,您的URL在到达终点(您的服务器)之前会经过很多地方,同时, 任何能够看到该流量的人都可以看到您的凭据,即使您不加加密地发送它们也毫不费力。
根据您将如何生成密钥,我建议使用对称或非对称加密:
如果您打算为所有客户端存储一个唯一的密码(顺便说一句,这也是一个坏主意,因为如果恶意用户破坏了您的密钥,他们可能会拥有您所有客户端的信息),则可以使用对称加密方法像AES。 您只需对消息进行加密,然后通过HTTP POST
发送消息(例如),然后在另一端将其解密。 很简单的概念。
如果您计划为每个客户生成密钥,那么您还需要以其他方式使服务器知道您生成的密钥,或者让客户知道为客户生成了哪个密钥(取决于您面对的方式)。它)。 在这种情况下,您可以使用“下一步”方法(基本上是我从所有这些方法中推荐的方法)。
您可以简单地使用非对称加密方法。 这意味着服务器生成一对密钥,一个是公共密钥,一个是私有密钥。 用户(客户端)将拥有公用的加密消息并发送到服务器的消息。 您可能想知道:我该如何保护我的消息,以便除了我的服务器之外没有人可以解密它们? 那就是私钥加入的地方,如果您拥有私钥,则只能解密消息。 这就是为什么您不希望与任何人共享它的原因(这就是它的名字来源)。 这样,您的客户可能会随时拥有您的公钥,而不会产生任何混淆需求,然后您可以使用它来加密一些文本并发送。 服务器将使用其私钥解密消息并进行相应处理。
最后一种方法的优点是:
您不必担心如何使您的密钥安全地到达另一方,因为它将被加密并且只有服务器才能解密。
您无需为每个客户生成密钥。
如果选择良好的非对称算法(例如SSL / TLS),则无需担心其破解(或者至少不像选择其他方法那样担心)。
替换旧的密钥对很容易,例如生成新的密钥对,替换旧的私有密钥并让您的客户拥有新的公共密钥。
您可能想看看这些链接:
String httpsURL = "https://www.abcd.com/auth/login/";
String query = "email="+URLEncoder.encode("abc@xyz.com","UTF-8");
query += "&";
query += "password="+URLEncoder.encode("abcd","UTF-8") ;
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-length", String.valueOf(query.length()));
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream output = new DataOutputStream(con.getOutputStream());
output.writeBytes(query);
output.close();
DataInputStream input = new DataInputStream( con.getInputStream() );
for( int c = input.read(); c != -1; c = input.read() )
System.out.print( (char)c );
input.close();
System.out.println("Resp Code:"+con .getResponseCode());
System.out.println("Resp Message:"+ con .getResponseMessage());
我所做的是为此使用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);
}
}
首先,永远不要使用密码本身,而只能使用密码的哈希表示(sha1函数)。 其次,您可以使用SSL(https)建立安全连接。 总结一下,在用户单击登录按钮后,从edittext获取密码并创建它的哈希。 在服务器端也使用哈希表示。 接下来,将数据作为https请求的正文发送到www.yoursite.com/login,请求正文中的将是您的数据。 发送为json fe ..
加密不是答案。
如果有人想要将URL,用户名和密码存储在客户端中,则无法避免。 即使已加密,您也必须向客户端提供解密密钥,然后可以将其自身反编译。
您不能阻止对服务接口进行反向工程。
因此,不能阻止其他客户端使用您的服务界面。 使用Fiddler嗅探网络流量很容易。 甚至SSL也没问题,因为我们可以在数据加密之前操纵客户端本身。
接下来是nKn的答案:
做您想做的一种方法是同时使用非对称和对称加密,您要做的是:
这种方法迫使客户端每次都生成一个新的对称密钥,因此您需要服务器为每个连接/会话保留正确的密钥。 如果需要静态对称密钥,则不能使用此方法,为此,可以使用另一种方法:
使用第二种方法,您只需将对称密钥存储在服务器上,而不必为每个连接/会话存储不同的密钥。 我仍然建议您定期更改对称密钥,以确保。
两种方法都不会强迫您将密钥硬编码到客户端代码中,也不会以明文形式发送对称密钥。 以明文形式发送的唯一内容是公钥,这根本不是问题,因此名称为“公钥”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.