哪里可以在App Engine上安全保存p12文件?

时间:2014-08-21 17:41:13

标签: security google-app-engine signing

在App Engine上,我需要一个p12文件来创建签名网址:

https://developers.google.com/storage/docs/accesscontrol#Signing-Strings

Google没有说明保留此文件的最佳做法。

我可以使用WEB-INF目录存储文件吗?然后它将成为源代码的一部分并与密码一起打开它。

这里的最佳做法是什么?还是其他方法?

-

性能怎么样?一遍又一遍地加载文件是否有效? App Engine是否自动在调用之间缓存文件(在同一实例上)?或者我需要使用servlet加载文件一次,然后以某种方式将其保存在静态变量中?有没有更好的方法来实现这一点,例如将文件存储在数据存储区记录中,然后将其保存在memcache中?这种方法有多安全?可能不好,对吗?

1 个答案:

答案 0 :(得分:6)

在App Engine中,文件存储周围存在许多不寻常的安全限制。我发现安全存储资源的最佳位置是使用捆绑包本身。如果您正在使用由appengine maven骨架项目生成的默认Maven设置,这就像将文件放在相应的资源目录中一样简单

Resources Directory Structure

一旦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;

      }

  }