Linux 设置 Java 系统属性而不将值放在命令行上
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5714812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting Java system properties without putting the values on the command line
提问by Tom Anderson
I have some Java code which depends on a system property super.secret.password
. I need to set that property when i run my app. The app will be started by a shell script, and the password will be kept in a file with minimal read permissions.
我有一些依赖于系统属性的 Java 代码super.secret.password
。我需要在运行我的应用程序时设置该属性。该应用程序将由 shell 脚本启动,密码将保存在具有最小读取权限的文件中。
I really don't want to write:
我真的不想写:
java -Dsuper.secret.password=letmein gov.fortknox.MyApp
Because then anyone who can get on to the machine and run ps
or top
can see what the password is.
因为这样任何人都可以进入机器并运行ps
或top
可以看到密码是什么。
So, is there a good way to set system properties without exposing them on the command line?
那么,有没有一种设置系统属性而不在命令行中暴露它们的好方法呢?
The only generic solution we've come up with is to write a small C program which reads system properties from a file, then starts the JVM using the JNI invocation API. Needless to say, we are not keen to do this.
我们提出的唯一通用解决方案是编写一个小型 C 程序,该程序从文件中读取系统属性,然后使用JNI 调用 API启动 JVM 。不用说,我们并不热衷于这样做。
If there isn't a way to set them without using the command line, is there a way to hide the command line from prying eyes? We're using Red Hat Enterprise Linux Server 5.5.
如果不使用命令行就没有办法设置它们,有没有办法隐藏命令行不被窥探?我们使用的是 Red Hat Enterprise Linux Server 5.5。
For what it's worth, the app in question is actually JBoss EAP 4.3.0, and we're using the system properties to fill in substitution constructs (${like.this}
) in its XML configuration files. There are JBoss-specific solutions - either use the SystemPropertiesService(by default, configured through the properties-service.xml file in the deploy directory) or pass the -P optionto run.sh. However, i am interested in the more general case, where this could be any Java program.
就其价值而言,有问题的应用程序实际上是 JBoss EAP 4.3.0,我们使用系统属性来填充${like.this}
其 XML 配置文件中的替换结构 ( )。有特定于 JBoss 的解决方案 - 要么使用SystemPropertiesService(默认情况下,通过部署目录中的 properties-service.xml 文件配置)或将-P 选项传递给 run.sh。但是,我对更一般的情况感兴趣,这可以是任何 Java 程序。
回答by Dakshinamurthy Karra
You can use JAVA_TOOL_OPTIONS environment variable and set the property there. But it will be visible still in your script file.
您可以使用 JAVA_TOOL_OPTIONS 环境变量并在那里设置属性。但它仍然在您的脚本文件中可见。
回答by WhiteFang34
You could just read the file somewhere near startup and call System.setProperty()
. For a web application use a ServletContextListener
so it happens early, see this answerfor a quick example.
您可以在启动附近的某个地方读取文件并调用System.setProperty()
. 对于 Web 应用程序,使用 aServletContextListener
以便它尽早发生,请参阅此答案以获取快速示例。
Update:this is perhaps not early enough for your use case with JBoss loading its configuration files.
更新:对于 JBoss 加载其配置文件的用例来说,这可能还不够早。
回答by David J. Liszewski
If your concern is exposing the value for super.secret.password
in clear text but you are not worried about someone invoking your program with the correct value for the password because of you've covered that issue using permissions or some other means, then I think you could simply encrypt the password in your start-up script and have a wrapper class decrypt it.
如果您担心super.secret.password
以明文形式公开 for 的值,但您不担心有人使用正确的密码值调用您的程序,因为您已经使用权限或其他方式解决了该问题,那么我认为您可以简单地加密启动脚本中的密码并使用包装类对其进行解密。
java -Dsuper.secret.password=BbWvOuliHZVHVwsXudsj14d1iXzo655R gov.fortknox.DecryptWrapper
If the credentials are for a data source, I should also point out other solutions specific to JBoss: SecureIdentityLoginModule
which essentially does the above, and PBEUtils
which offers a keystore solution when used with SecureIdentityLoginModule
. See EncryptingDataSourcePasswords.
如果凭据用于数据源,我还应该指出其他特定于JBoss 的解决方案:SecureIdentityLoginModule
它基本上完成了上述工作,并且PBEUtils
在与SecureIdentityLoginModule
. 请参阅EncryptingDataSourcePasswords。
And finally, the suggestion by Peter Laweryto use a file is valid too.
最后,Peter Lawery使用文件的建议也是有效的。
回答by Chii
if an attacker has physical access to your machine, then there is no real reason why they can't own the machine - a simple rot13 to avert the casual eye is plenty.
如果攻击者可以物理访问您的机器,那么他们就没有真正的理由不能拥有这台机器——一个简单的 rot13 来避免不经意的目光就足够了。
If an attacker has some privileges (such as running top for example), but not physical access, then you can execute the program under a specialized user account (e.g., web-server-user), which has very little privilege, but has exclusive read access to a file containing the password. you then start up the app using that user account, and pass in the file path.
如果攻击者有一些权限(例如运行 top),但没有物理访问权限,那么您可以在专门的用户帐户(例如 web-server-user)下执行程序,该帐户的权限很小,但具有独占权限对包含密码的文件的读取权限。然后使用该用户帐户启动应用程序,并传入文件路径。
Doing so relies on the access privilege restrictions in the OS, which is likely to be implemented much better than what you can roll yourself.
这样做依赖于操作系统中的访问权限限制,这可能比您自己滚动的更好。
回答by Bill Birch
'cryptomainia' was written to solve this exact issue. It decrypts main() arguments. https://github.com/birchb1024/cryptomainia
编写“cryptomainia”就是为了解决这个确切的问题。它解密 main() 参数。https://github.com/birchb1024/cryptomainia
回答by user2038872
You can read it from some file in a static initializer of your class that contains the main method:
您可以从包含 main 方法的类的静态初始值设定项中的某个文件中读取它:
static {
try {
FileReader fr = new FileReader(FILE_NAME);
// read the property
System.setProperty(property.getName(), property.getValue());
} catch (final FileNotFoundException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
} catch (final IOException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}
...
public static void main(...){
...
}