我刚刚开始在我的Django后端实现FCM。
我遇到的问题如下。
在the docs中,系统会告诉您生成私钥JSON文件并安全地存储它。 通常我将我的密钥存储在os.env变量中。但这是不可能的,因为这是一个完整的文件,而不仅仅是一个值。同样在同一页面上,doc会告诉您如何获取请求令牌:
def _get_access_token():
"""Retrieve a valid access token that can be used to authorize requests.
:return: Access token.
"""
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'service-account.json', SCOPES)
access_token_info = credentials.get_access_token()
return access_token_info.access_token
正如您在此处所见,库需要直接访问该文件。
所以我的问题是?我该如何安全存储?我目前在heroku上托管,所以我需要在我的版本控制系统中使用它。
答案 0 :(得分:3)
我们这样做的方式:
加密资源文件中的json字符串/ Store 解密密钥,存储为Env变量。
创建凭据时解密加密的字符串。
答案 1 :(得分:2)
这是基于ivanspenchev在他的帖子中提出的建议。
流程是:读取json数据 - >用密钥加密 - >用密钥解密。我没有使用他建议的加密算法,因为我不喜欢它。
但基本的想法是,你有一个课程" EncryptEngine"做两件事,加密一个字符串,并解密一个字符串。
public class EncryptEngine
{
Cipher ecipher;
Cipher dcipher;
// 8-byte Salt
byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
};
// Iteration count
int iterationCount = 19;
public EncryptEngine() {
}
/**
*
* @param secretKey Key used to encrypt data
* @param plainText Text input to be encrypted
* @return Returns encrypted text
* @throws java.security.NoSuchAlgorithmException
* @throws java.security.spec.InvalidKeySpecException
* @throws javax.crypto.NoSuchPaddingException
* @throws java.security.InvalidKeyException
* @throws java.security.InvalidAlgorithmParameterException
* @throws java.io.UnsupportedEncodingException
* @throws javax.crypto.IllegalBlockSizeException
* @throws javax.crypto.BadPaddingException
*
*/
public String encrypt(String secretKey, String plainText)
throws NoSuchAlgorithmException,
InvalidKeySpecException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
IllegalBlockSizeException,
BadPaddingException {
//Key generation for enc and desc
KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
//Enc process
ecipher = Cipher.getInstance(key.getAlgorithm());
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
String charSet = "UTF-8";
byte[] in = plainText.getBytes(charSet);
byte[] out = ecipher.doFinal(in);
String encStr = new String(Base64.getEncoder().encode(out));
return encStr;
}
/**
* @param secretKey Key used to decrypt data
* @param encryptedText encrypted text input to decrypt
* @return Returns plain text after decryption
* @throws java.security.NoSuchAlgorithmException
* @throws java.security.spec.InvalidKeySpecException
* @throws javax.crypto.NoSuchPaddingException
* @throws java.security.InvalidKeyException
* @throws java.security.InvalidAlgorithmParameterException
* @throws java.io.UnsupportedEncodingException
* @throws javax.crypto.IllegalBlockSizeException
* @throws javax.crypto.BadPaddingException
*/
public String decrypt(String secretKey, String encryptedText)
throws NoSuchAlgorithmException,
InvalidKeySpecException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
IllegalBlockSizeException,
BadPaddingException,
IOException {
//Key generation for enc and desc
KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
//Decryption process; same key will be used for decr
dcipher = Cipher.getInstance(key.getAlgorithm());
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
byte[] enc = Base64.getDecoder().decode(encryptedText);
byte[] utf8 = dcipher.doFinal(enc);
String charSet = "UTF-8";
String plainStr = new String(utf8, charSet);
return plainStr;
}
public static void main(String[] args) throws Exception {
EncryptEngine cryptoUtil=new EncryptEngine();
String key="ezeon8547";
JsonFactory f = new JsonFactory();
JsonParser jp =
f.createJsonParser(/MyDocuments/Repo/Myproject/service-account.json);
String plain;
while (jp.nextToken() == JsonToken.START_OBJECT)) {
plain += jp.toString();
}
String enc=cryptoUtil.encrypt(key, plain);
System.out.println("Original text: "+plain);
System.out.println("Encrypted text: "+enc);
String plainAfter=cryptoUtil.decrypt(key, enc);
System.out.println("Original text after decryption: "+plainAfter);
}
}
答案 2 :(得分:1)
大多数团队将JSON文件保留在版本控制之外并手动添加到环境中。
虽然与保持环境变量中的值不完全相同,但它具有类似的安全性。只能访问版本控制的开发人员无法访问密钥,开发人员也不会意外地使用生产密钥在自己的系统上运行。但另一方面:有权访问生产服务器的人可以在两种情况下获得密钥。
答案 3 :(得分:0)