Google app engine 如何保护使用Google云端点构建的API?

Google app engine 如何保护使用Google云端点构建的API?,google-app-engine,google-cloud-platform,google-cloud-endpoints,Google App Engine,Google Cloud Platform,Google Cloud Endpoints,API是移动应用程序的后端。我不需要用户身份验证。我只需要一种方法来保护对这个API的访问。目前,我的后端已公开 似乎只讨论用户身份验证和授权,这不是我在这里需要的。我只需要确保只有我的移动应用程序可以与此后端通话,而不能与其他任何人通话。是的,您可以这样做:使用身份验证来保护您的端点,而无需进行用户身份验证 我发现这种方法没有很好的文档记录,实际上我自己也没有这样做,但我打算这样做,所以当我在一些IO13视频中看到它被讨论时,我就注意到了(我想这就是我看到它的地方): 以下是我对所涉及内容的理

API是移动应用程序的后端。我不需要用户身份验证。我只需要一种方法来保护对这个API的访问。目前,我的后端已公开


似乎只讨论用户身份验证和授权,这不是我在这里需要的。我只需要确保只有我的移动应用程序可以与此后端通话,而不能与其他任何人通话。

是的,您可以这样做:使用身份验证来保护您的端点,而无需进行用户身份验证

我发现这种方法没有很好的文档记录,实际上我自己也没有这样做,但我打算这样做,所以当我在一些IO13视频中看到它被讨论时,我就注意到了(我想这就是我看到它的地方):

以下是我对所涉及内容的理解:

  • 创建一个GoogleAPI项目(尽管除了身份验证本身之外,这实际上并不涉及他们的API)
  • 创建宣誓客户端ID,该ID通过其包名和您将使用的证书的SHA1指纹绑定到您的应用程序
您将这些客户端ID添加到端点的可接受ID列表中。您将向端点添加用户参数,但由于未指定用户,因此该参数将为null

@ApiMethod(
   name = "sendInfo",
   clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID },
   audiences = { Config.WEB_CLIENT_ID } 
   // Yes, you specify a 'web' ID even if this isn't a Web client.
)
public void sendInfo(User user, Info greeting) {
关于上述内容,这里有一些不错的文档:

制定端点服务调用时,您的客户端应用程序将指定这些客户端ID。所有宣誓细节都将在客户端设备的后台处理,以便将客户端ID转换为身份验证令牌

HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( ctx, Config.WEB_CLIENT_ID );
//credential.setSelectedAccountName( user );  // not specify a user
Myendpoint.Builder builder = new Myendpoint.Builder( transport, jsonFactory, credential );  

这个客户端代码只是我最好的猜测-对不起。如果其他人对客户端代码应该是什么样子有参考,那么我也会感兴趣。

很抱歉,谷歌没有为您的问题提供解决方案(这也是我的问题)。 您可以使用他们的API密钥机制(请参阅),但由于谷歌自己的API explorer(请参阅),该策略存在一个巨大的漏洞,这是一个测试API的伟大开发工具,但公开了所有云端点API,而不仅仅是谷歌的服务API。这意味着任何拥有您的项目名称的人都可以随意浏览和调用您的API,因为API explorer绕过了API密钥安全性。 我找到了一个解决方法(基于bossylobster对这篇文章的出色响应:),即在客户端API中传递一个不属于消息请求定义的请求字段,然后在API服务器中读取它。如果找不到undocumented字段,则引发未经授权的异常。这将堵塞API资源管理器创建的孔。 在iOS(我用于我的应用程序)中,您向每个请求类(由Google的API生成器工具创建的类)添加一个属性,如下所示:

并将其值设置为您选择的键。在您的服务器代码(在我的例子中是python)中,您检查它是否存在,如果您没有看到它或它没有设置为您的服务器和客户机将同意的值,则检查它是否存在:

mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
        if mykey != 'my_supersecret_key':
            raise endpoints.UnauthorizedException('No, you dont!')
希望这能让你走上正轨

本文档仅供客户使用。我需要的是文件 介绍如何在服务器端提供服务帐户功能

这可能意味着两件不同的事情,但我想谈谈我认为问题所在。如果您只希望您的服务帐户访问您的服务,那么您只需将服务帐户的clientId添加到@Api/@ApiMethod注释中,构建一个GoogleCredential,然后像往常一样调用您的服务。具体地说

在google开发者控制台中,创建一个新的服务帐户。这将创建一个自动下载的.p12文件。客户端在您链接到的文档中使用此选项如果你不能保证.p12的安全,那么这并不比密码更安全。我猜这就是为什么云端点文档中没有明确列出的原因

将google开发者控制台中显示的客户端ID添加到@Api或@ApiMethod注释中的clientID中

import com.google.appengine.api.users.User

@ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE }, 
     clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" })
public void doIt(User user){ //by convention, add User parameter to existing params
    // if no client id is passed or the oauth2 token doesn't 
    // match your clientId then user will be null and the dev server 
    // will print a warning message like this:
    // WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed
    //..
}
构建客户机的方式与构建不安全版本的方式相同,唯一的区别是创建一个GoogleCredential对象以传递给服务的MyService.Builder

HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish
JsonFactory jsonFactory = new JacksonFactory();

// assuming you put the .p12 for your service acccount 
// (from the developer's console) on the classpath; 
// when you deploy you'll have to figure out where you are really
// going to put this and load it in the appropriate manner 
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12");
File p12file = new File(url.toURI());

GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport);
credentialBuilder.setJsonFactory(jsonFactory);
//NOTE: use service account EMAIL (not client id)
credentialBuilder.setServiceAccountId("12345678901-12acg1ez8lf51spfl06lznd1dsasdfj@developer.gserviceaccount.com");    credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"));
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file);
GoogleCredential credential = credentialBuilder.build();
现在以同样的方式调用生成的客户机 您可能会选择不安全的版本,除非生成器采用 我们上面的谷歌凭证是最后一个参数

MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");

final MyService service = builder.build();
// invoke service same as unsecured version

实际上,您正在谈论身份验证和授权。您如何建议只为您的应用程序保护端点,而不进行某种形式的身份验证(基于应用程序或最终用户的身份验证)。端点只是遵循特定公共api的web服务。实现这一点的一个示例方法是服务帐户:然而,这仅适用于Google api。本文档仅供客户使用。我需要的是关于如何在服务器端提供服务帐户功能的文档。另一种方法是在应用程序和端点Tom之间使用您自己的哈希值,我正在dev上尝试,但传递的用户始终为null,即使授权是使用GAE项目中使用的我的电子邮件id完成的。我在@Apimethod中提供的客户端id不应该是错误的,因为我正在成功地使用它访问google云存储。你能用吗?不行。我尝试了web客户端。但我可以打任何客户的电话。也许它应该阻止除我的客户端id之外的客户端。但它不会。您不能在凭据中“不指定用户”。setSelectedAccountName();-它需要一个必需的字符串参数…您尝试过这个吗?汤姆:这对你有用吗@MicroR:你是说它需要空字符串吗?@sam,对不起,我不记得了-我不再参与这个领域了。@Tom谢谢你。但是如果有人反编译你的Android APK,他们不能只看到纯文本请求字段,然后创建另一个Android应用程序并使用你的API吗?在javasc中
MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");

final MyService service = builder.build();
// invoke service same as unsecured version