Java - 从配置文件加密/解密用户名和密码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/339004/
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
Java - encrypt / decrypt user name and password from a configuration file
提问by nzpcmad
We are busy developing a Java web service for a client. There are two possible choices:
我们正忙于为客户开发 Java Web 服务。有两种可能的选择:
Store the encrypted user name / password on the web service client. Read from a config. file on the client side, decrypt and send.
Store the encrypted user name / password on the web server. Read from a config. file on the web server, decrypt and use in the web service.
将加密的用户名/密码存储在 Web 服务客户端上。从配置中读取。文件在客户端,解密并发送。
将加密的用户名/密码存储在 Web 服务器上。从配置中读取。Web 服务器上的文件,解密并在 Web 服务中使用。
The user name / password is used by the web service to access a third-party application.
Web 服务使用用户名/密码来访问第三方应用程序。
The client already has classes that provide this functionality but this approach involves sending the user name / password in the clear (albeit within the intranet). They would prefer storing the info. within the web service but don't really want to pay for something they already have. (Security is not a big consideration because it's only within their intranet).
客户端已经有提供此功能的类,但这种方法涉及以明文形式发送用户名/密码(尽管是在内部网中)。他们更愿意存储信息。在网络服务中,但真的不想为他们已经拥有的东西付费。(安全性不是一个重要的考虑因素,因为它只在他们的内部网中)。
So we need something quick and easy in Java.
所以我们需要一些在 Java 中快速而简单的东西。
Any recommendations?
有什么建议吗?
The server is Tomkat 5.5. The web service is Axis2.
服务器是 Tomkat 5.5。Web 服务是 Axis2。
- What encrypt / decrypt package should we use?
- What about a key store?
- What configuration mechanism should we use?
- Will this be easy to deploy?
- 我们应该使用什么加密/解密包?
- 钥匙店呢?
- 我们应该使用什么配置机制?
- 这会容易部署吗?
采纳答案by erickson
Being on the intranet certainly does not justify dismissing security. Most damage done to information is by insiders. Look at the value of what's being protected, and give due consideration to security.
在 Intranet 上当然不能成为忽视安全性的理由。对信息造成的大部分损害是内部人员造成的。查看受保护内容的价值,并适当考虑安全性。
It sounds like there's a third-party application, for which you have one set of credentials, and some clients that effectively share this identity when using the third-party application. If that's the case, I recommend the following approach.
听起来好像有一个第三方应用程序,您有一组凭据,并且一些客户端在使用第三方应用程序时有效地共享此身份。如果是这种情况,我推荐以下方法。
Don't distribute the third-party password beyond your web server.
不要将第三方密码分发到您的 Web 服务器之外。
The safest way to do this is to provide it to the web application interactively. This could be ServletContextListener that prompts for the password as the application starts, or a page in the application so that a admin can enter it through a form. The password is stored in the ServletContext and used to authenticate requests to the third-party service.
执行此操作的最安全方法是以交互方式将其提供给 Web 应用程序。这可以是在应用程序启动时提示输入密码的 ServletContextListener,也可以是应用程序中的一个页面,以便管理员可以通过表单输入密码。密码存储在 ServletContext 中,用于验证对第三方服务的请求。
A step down in safety is to store the password on the server's file system so that it's readable only by the user running the server. This relies on the server's file system permissions for protection.
安全的一个步骤是将密码存储在服务器的文件系统上,以便只有运行服务器的用户才能读取它。这依赖于服务器的文件系统权限进行保护。
Trying to store an encrypted form of the password, on the client or the server, is just taking one step backward. You fall into an infinite regress when trying to protect a secret with another secret.
尝试在客户端或服务器上存储加密形式的密码只是向后退了一步。当你试图用另一个秘密保护一个秘密时,你会陷入无限倒退。
In addition, the clients should authenticate themselves to the server. If the client is interactive, have the users enter a password. The server can then decide if that user is authorized to access the third-party service. If the client is not interactive, the next best security is to protect the client's password using file system permissions.
此外,客户端应该向服务器验证自己。如果客户端是交互式的,请让用户输入密码。然后服务器可以决定该用户是否有权访问第三方服务。如果客户端不是交互式的,那么下一个最好的安全措施是使用文件系统权限保护客户端的密码。
To protect the clients' credentials, the channel between the client and your web server should be protected with SSL. Here, operating on an intranet is advantageous, because you can use a self-signed certificate on the server.
为了保护客户端的凭据,客户端和您的 Web 服务器之间的通道应该使用 SSL 进行保护。在这里,在 Intranet 上操作是有利的,因为您可以在服务器上使用自签名证书。
If you do store passwords in a file, put them in a file by themselves; it makes the need to manage permissions carefully more conspicuous, and minimizes the need for many users to be editing that file and thus seeing the password.
如果您确实将密码存储在文件中,请将它们自己放在一个文件中;它使仔细管理权限的需要更加明显,并最大限度地减少了许多用户编辑该文件从而看到密码的需要。
回答by Gennady Shumakher
As I understand anyhow in order to call 3rd party web service you pass password as plain text and no security certificates are involved.
据我了解,无论如何,为了调用 3rd 方网络服务,您将密码作为纯文本传递,并且不涉及安全证书。
Then I would say the easiest approach would be to store password in encrypted format (via java encryption mechanism) when the encryption/decryption key is just hard coded in the code.
然后我会说,当加密/解密密钥只是硬编码在代码中时,最简单的方法是以加密格式(通过 java 加密机制)存储密码。
I would definitely store it on the server side (file system or db) rather then distribute and maintain it on the multiple clients.
我肯定会将它存储在服务器端(文件系统或数据库),而不是在多个客户端上分发和维护它。
Here is how that could work with "DES" encryption:
以下是“DES”加密的工作方式:
// only the first 8 Bytes of the constructor argument are used
// as material for generating the keySpec
DESKeySpec keySpec = new DESKeySpec("YourSecr".getBytes("UTF8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
sun.misc.BASE64Encoder base64encoder = new BASE64Encoder();
sun.misc.BASE64Decoder base64decoder = new BASE64Decoder();
.........
// ENCODE plainTextPassword String
byte[] cleartext = plainTextPassword.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe
cipher.init(Cipher.ENCRYPT_MODE, key);
String encrypedPwd = base64encoder.encode(cipher.doFinal(cleartext));
// now you can store it
......
// DECODE encryptedPwd String
byte[] encrypedPwdBytes = base64decoder.decodeBuffer(encryptedPwd);
Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes));