我的设置:

  • Python,使用endpoints_proto_datastore的Google App引擎
  • iOS,端点Obj-C客户端库生成器

  • 背景

    我已经安装了一个测试Google云端端点api,并使其运行非常快。使用iOS模拟器中的测试应用程序以及使用Google的API Explorer,效果很好。该API当前对所有人开放,且不进行身份验证。

    我想:设置可以由应用程序使用的API key 或系统凭据,以确保应用程序可以单独访问api -拒绝所有其他应用程序。

    Google Endpoints Auth文档(1)中的方法是使用Google Developers Console(2)创建OAuth 2.0客户端ID。因此,我为类型为iOS的已安装应用程序创建了一个ID。到现在为止还挺好。

    在应用程序中,GTLService对象如下所示:
    -(GTLServiceDemogaeapi *)myApiService {
        GTMOAuth2Authentication *auth = [[GTMOAuth2Authentication alloc] init];
        auth.clientID = @"10???????????????????ie.apps.googleusercontent.com";
        auth.clientSecret = @"z????????????3";
        auth.scope = @"https://www.googleapis.com/auth/userinfo.email";
    
        static GTLServiceDemogaeapi *service = nil;
        if (!service) {
            service = [[GTLServiceDemogaeapi alloc] init];
            service.authorizer = auth;
            service.retryEnabled = YES;
            [GTMHTTPFetcher setLoggingEnabled:YES];
        }
        return service;
     }
    

    在GAE上,我指定了(allowed_client_ids,并向方法添加了用户检查...
    @endpoints.api(name='demogaeapi', version='v1',
                   allowed_client_ids=['10?????????????ie.apps.googleusercontent.com',
                   endpoints.API_EXPLORER_CLIENT_ID],
                   scopes=[endpoints.EMAIL_SCOPE],
                   description='My Demo API')
    class MyApi(remote.Service):
    
        @TestModel.method(path='testmodel/{id}', name='testmodel.insert', http_method='POST')
        def testModelInsert(self, test_model):
    
            current_user = endpoints.get_current_user()
            if current_user is None:
                raise endpoints.UnauthorizedException('Invalid token.')
    

    问题

    current_user始终为None,因此该方法将始终引发异常。看来这是一个已知的问题,发行号8848:Google Cloud Enpoints get_current_user API不会立即填充user_id(3),没有修复的可能。

    选项?
  • 等到Google修复问题8848。确实不能,我们有产品要发布!

  • 编辑:2015年5月15日-Google发行了8848版,其状态为WontFix。
  • 我看到可能可以使用API​​ key ,但是虽然我已经能够创建一个API key -我还没有找到在后端启用它的方法。我还注意到,此方法有一个大漏洞,Google的API Explorer可以击败它,请参阅问题(4)。
  • 是否在此处(5)中所述的 @ endpoints.api参数:auth_level 提供了答案?我尝试使用:
    @endpoints.api(name='demogaeapi', version='v1',
           auth_level=endpoints.AUTH_LEVEL.REQUIRED,
           scopes=[endpoints.EMAIL_SCOPE],
           description='My Demo API')
    

    但是能够在不使用凭据的情况下使用客户端应用程序中的api。因此,它显然没有添加任何身份验证。
  • 向具有共享 key 的客户端查询中添加一个hiddenProperty。如此处的bossylobster(6)和此处的Carlos(7)所述。我尝试了此操作,但看不到如何获得原始请求对象(另一个问题How to get at the request object when using endpoints_proto_datastore.ndb?的主题)。
    @TestModel.method(path='testmodel/{id}', name='testmodel.insert', http_method='POST')
    def testModelInsert(self, test_model):
    
        mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
        if mykey != 'my_supersecret_key':
            raise endpoints.UnauthorizedException('No, you dont!')
    

  • 编辑:另一个选择浮出水面:
  • 使用Google Developers Console(2)创建一个服务帐户。使用此帐户无需用户同意(通过UI)即可访问API。但是,Google似乎将可以通过这种方式添加的应用程序数量限制为15或20。请参阅Google OAuth2文档(8)。我们可能会超出限制。

  • 问题

    有谁知道我如何使这些选项中的任何一个起作用?还是我应该以不同的方式来处理这个问题?

    如您所见,我需要指导,帮助,想法...

    由于我需要10个声誉才能发布2个以上的链接:这是我必须提取并添加为引用的链接。确实破坏了问题的流程。
  • cloud.google.com/appengine/docs/python/endpoints/auth
  • console.developers.google.com/
  • code.google.com/p/googleappengine/issues/detail?id=8848
  • stackoverflow.com/a/26133926/4102061
  • cloud.google.com/appengine/docs/python/endpoints/create_api
  • stackoverflow.com/a/16803274/4102061
  • stackoverflow.com/a/26133926/4102061
  • developers.google.com/accounts/docs/OAuth2
  • 最佳答案

    一个很好的问题,一个真正的问题。我通过拥有自己的“用户”数据库表解决了该问题。 Long key (我使用Java)在写入时自动生成,这是我从那时起用来唯一标识用户的值。还写入该表的是Google ID(如果通过网页调用时提供),电子邮件地址和iOS ID(在未登录Google帐户的情况下使用iOS应用程序时)。

    当我的AppEngine端点被调用时,我使用User参数(仅是已登录客户端的经过身份验证的电子邮件地址)或单独的可选iosid参数中存在的信息,以便从所述表中获取我的内部用户ID编号并使用从那时起可以唯一地标识我的用户。

    我也使用同一张表来存储其他特定于用户的信息,所以它实际上与尝试使用current_user作为主键没有什么不同,除了我必须对三个字段(googleid,email和iosid)建立索引以进行查找。

    09-10 14:24
    查看更多