在App Engine上,我需要一个p12文件来创建签名网址:
https://developers.google.com/storage/docs/accesscontrol#Signing-Strings
Google没有说明保留此文件的最佳做法。
我可以使用WEB-INF目录存储文件吗?然后它将成为源代码的一部分并与密码一起打开它。
这里的最佳做法是什么?还是其他方法?
-
性能怎么样?一遍又一遍地加载文件是否有效? App Engine是否自动在调用之间缓存文件(在同一实例上)?或者我需要使用servlet加载文件一次,然后以某种方式将其保存在静态变量中?有没有更好的方法来实现这一点,例如将文件存储在数据存储区记录中,然后将其保存在memcache中?这种方法有多安全?可能不好,对吗?
答案 0 :(得分:6)
在App Engine中,文件存储周围存在许多不寻常的安全限制。我发现安全存储资源的最佳位置是使用捆绑包本身。如果您正在使用由appengine maven骨架项目生成的默认Maven设置,这就像将文件放在相应的资源目录中一样简单
一旦p12位于正确的位置,您将需要使用类加载器的GetResourceAsStream函数加载它。然后在构建GoogleCredentials时,不要使用文档化的setServiceAccountPrivateKeyFromP12File()函数,而是使用setServiceAccountPrivateKey()函数并传入刚刚构造的PrivateKey。
此外,您很可能不希望将任何此功能与实时的appengine实例一起使用,因为在这种情况下,Appengine已经为您提供了更容易使用的AppIdentityCredentials功能,因此您可能希望检测您的应用是否处于生产模式,并且在使用localhost进行测试时仅使用ServiceAccount。
将所有这些功能放在一起产生以下功能,对我有用:
public static HttpRequestInitializer getDefaultCredentials() throws IOException
{
List<String> scopes = Arrays.asList(new String[] {DEVSTORAGE_FULL_CONTROL});
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production)
return new AppIdentityCredential(scopes);
else
{
GoogleCredential credential;
try {
String p12Password = "notasecret";
ClassLoader classLoader = ServiceUtils.class.getClassLoader();
KeyStore keystore = KeyStore.getInstance("PKCS12");
InputStream keyFileStream = classLoader.getResourceAsStream("key.p12");
if (keyFileStream == null){
throw new Exception("Key File Not Found.");
}
keystore.load(keyFileStream, p12Password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey("privatekey", p12Password.toCharArray());
credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("YOUR_SERVICE_ACCOUNT_EMAIL@developer.gserviceaccount.com")
.setServiceAccountPrivateKey(key)
.setServiceAccountScopes(scopes)
.build();
} catch (GeneralSecurityException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
return credential;
}
}