[英]Where should properties like “SERVER_URL” live in a gradle-based Android project?
Where should I define constants like SERVER_URL or some static passwords in a Gradle Android project? 我应该在Gradle Android项目中哪里定义SERVER_URL等常量或一些静态密码? Obviously, I will use it in code.
显然,我会在代码中使用它。
build.gradle
file as a build config field build.gradle
文件中作为构建配置字段 gradle.properties
file (I don't know how get these properties by code) gradle.properties
文件中(我不知道如何通过代码获取这些属性) props
file located in res
folder res
文件夹中的props
文件中 How secure is it in each case? 在每种情况下它有多安全?
Thanks. 谢谢。
There are two approaches in your question. 您的问题有两种方法。
1> To store static URL in your application
1>在应用程序中存储静态URL
The fact someone can see the URL doesn't matter (they could get this by sniffing the network anyway). 有人可以看到URL并不重要(他们可以通过嗅探网络得到这个)。 You probably want to ensure the request has come from a trusted client.
您可能希望确保请求来自可信客户端。 You can also maintain some key in request also.
您还可以在请求中维护一些密钥。
2> To store password in your application
2>在应用程序中存储密码
I found a good solution to store it in SharedPreferences with encryption. 我找到了一个很好的解决方案,可以将它存储在SharedPreferences中并加密。 Copy/Paste below code to create encrypted SharedPreferences.
复制/粘贴下面的代码以创建加密的SharedPreferences。
Simply wrap your own SharedPreferences object in this one, and any data you read/write will be automatically encrypted and decrypted. 只需将您自己的SharedPreferences对象包装在此对象中,您读/写的任何数据都将自动加密和解密。 eg.
例如。
final SharedPreferences prefs = new ObscuredSharedPreferences(
this, this.getSharedPreferences(YOUR_PREFS_FILE_NAME, Context.MODE_PRIVATE) );
// eg.
prefs.edit().putString("test","test").commit();
prefs.getString("test", null);
Class code, 班级代码,
/**
* Warning, this gives a false sense of security. If an attacker has enough access to
* acquire your password store, then he almost certainly has enough access to acquire your
* source binary and figure out your encryption key. However, it will prevent casual
* investigators from acquiring passwords, and thereby may prevent undesired negative
* publicity.
*/
public class ObscuredSharedPreferences implements SharedPreferences {
protected static final String UTF8 = "utf-8";
private static final char[] SEKRIT = ... ; // INSERT A RANDOM PASSWORD HERE.
// Don't use anything you wouldn't want to
// get out there if someone decompiled
// your app.
protected SharedPreferences delegate;
protected Context context;
public ObscuredSharedPreferences(Context context, SharedPreferences delegate) {
this.delegate = delegate;
this.context = context;
}
public class Editor implements SharedPreferences.Editor {
protected SharedPreferences.Editor delegate;
public Editor() {
this.delegate = ObscuredSharedPreferences.this.delegate.edit();
}
@Override
public Editor putBoolean(String key, boolean value) {
delegate.putString(key, encrypt(Boolean.toString(value)));
return this;
}
@Override
public Editor putFloat(String key, float value) {
delegate.putString(key, encrypt(Float.toString(value)));
return this;
}
@Override
public Editor putInt(String key, int value) {
delegate.putString(key, encrypt(Integer.toString(value)));
return this;
}
@Override
public Editor putLong(String key, long value) {
delegate.putString(key, encrypt(Long.toString(value)));
return this;
}
@Override
public Editor putString(String key, String value) {
delegate.putString(key, encrypt(value));
return this;
}
@Override
public void apply() {
delegate.apply();
}
@Override
public Editor clear() {
delegate.clear();
return this;
}
@Override
public boolean commit() {
return delegate.commit();
}
@Override
public Editor remove(String s) {
delegate.remove(s);
return this;
}
}
public Editor edit() {
return new Editor();
}
@Override
public Map<String, ?> getAll() {
throw new UnsupportedOperationException(); // left as an exercise to the reader
}
@Override
public boolean getBoolean(String key, boolean defValue) {
final String v = delegate.getString(key, null);
return v!=null ? Boolean.parseBoolean(decrypt(v)) : defValue;
}
@Override
public float getFloat(String key, float defValue) {
final String v = delegate.getString(key, null);
return v!=null ? Float.parseFloat(decrypt(v)) : defValue;
}
@Override
public int getInt(String key, int defValue) {
final String v = delegate.getString(key, null);
return v!=null ? Integer.parseInt(decrypt(v)) : defValue;
}
@Override
public long getLong(String key, long defValue) {
final String v = delegate.getString(key, null);
return v!=null ? Long.parseLong(decrypt(v)) : defValue;
}
@Override
public String getString(String key, String defValue) {
final String v = delegate.getString(key, null);
return v != null ? decrypt(v) : defValue;
}
@Override
public boolean contains(String s) {
return delegate.contains(s);
}
@Override
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
delegate.registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
}
@Override
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener onSharedPreferenceChangeListener) {
delegate.unregisterOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);
}
protected String encrypt( String value ) {
try {
final byte[] bytes = value!=null ? value.getBytes(UTF8) : new byte[0];
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP),UTF8);
} catch( Exception e ) {
throw new RuntimeException(e);
}
}
protected String decrypt(String value){
try {
final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0];
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
return new String(pbeCipher.doFinal(bytes),UTF8);
} catch( Exception e) {
throw new RuntimeException(e);
}
}
}
Edit 编辑
You can use NDK to store password constant. 您可以使用NDK来存储密码常量。 To store and retrieve your key, you need to write the following code in our application.
要存储和检索密钥,您需要在我们的应用程序中编写以下代码。
static {
System.loadLibrary("library-name");
}
public native String getSecretKey();
And save in a file using NDK the following function 并使用NDK保存在文件中以下功能
Java_com_example_exampleApp_ExampleClass_getSecretKey( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "giveMeSecretKey".");
}
Now you can easily retrieve our key and use it to encrypt our data. 现在,您可以轻松检索我们的密钥并使用它来加密我们的数据。
byte[] keyPassword = getSecretKey().getBytes();
One approach would be to define every sensitive value in gradle.properties, and ensure that this file is excluded from VCS. 一种方法是在gradle.properties中定义每个敏感值,并确保从VCS中排除此文件。 You can then get Gradle to add string resources into your build, which are accessible in the normal way.
然后,您可以让Gradle将字符串资源添加到您的构建中,这些资源可以通过正常方式访问。 This has the added advantage that you can use different values for different product flavors.
这具有额外的优势,您可以为不同的产品口味使用不同的值。
// gradle.properties
MY_SECRET_PASSWORD=password
// build.gradle
buildTypes {
debug {
resValue "string", "my_secret_password", MY_SECRET_PASSWORD
}
}
// MainActivity.java
String password = getString(R.string.my_secret_password);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.