草庐IT

android - 从 Android OAuth2 访问谷歌云存储

coder 2023-11-22 原文

我正在尝试设计一个应用程序,它可以从我的 Google 云存储帐户下载适当的声音文件。该应用不访问用户帐户,而是访问我自己的帐户。

我的阅读使我相信最合适的模型是 服务帐户 https://code.google.com/p/google-api-java-client/wiki/OAuth2#Service_Accounts

不幸的是,开发人员决定不提供 Android 示例。他们确实用纯 Java 提供了一个很好的例子,它可以工作 http://samples.google-api-java-client.googlecode.com/hg/storage-serviceaccount-cmdline-sample/instructions.html?r=default

我尝试将其改编为适用于 Android,但遇到了问题。

GoogleCredential credential =
        new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY).setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes(STORAGE_SCOPE)
            .setServiceAccountPrivateKeyFromP12File(new File("key.p12")).build();

在 Google 的示例中,他们传递了 key.p12 文件,但是在 Android 上,当我将文件放在 res/raw 文件夹中时,我访问它的唯一方法似乎是作为输入流。我找不到将文件传递给 JSON 的优雅方法。

这一切让我相信我一定做错了什么。 我应该使用 key.p12 我应该使用“服务帐户模型”吗? 有没有例子/

谢谢 瑞安


一个更新 我设法实现了让它工作的目标,但我觉得我的解决方案很笨拙,我确信这不是预期的方式

我所做的是将 key.p12 添加为我作为输入流打开的原始/资源。然后我使用示例中所示的库将其转换为私钥。

http://www.flexiprovider.de/examples/ExampleSMIMEsign.html

我的代码是这样的

Security.addProvider(new de.flexiprovider.core.FlexiCoreProvider());
    // Next, we have to read the private PKCS #12 file, since the the
    // private key used for signing is contained in this file:
    DERDecoder dec = new DERDecoder(getResources().openRawResource(
            R.raw.key));
    PFX pfx = new PFX();
    try {
        pfx.decode(dec);
        SafeBag safeBag = pfx.getAuthSafe().getSafeContents(0)
                .getSafeBag(0);
        PKCS8ShroudedKeyBag kBag = (PKCS8ShroudedKeyBag) safeBag
                .getBagValue();
        char[] password = "my password from google api".toCharArray();
        privKey = kBag.getPrivateKey(password);
        new AsyncLoadStorage(this).execute();
    } catch (ASN1Exception e) {

但整个事情很难看,我想要一个更干净的解决方案

最佳答案

Google 文档实际上具有误导性。他们没有更新他们的控制台链接(继续要求您寻找“注册应用程序”链接,该链接不存在),并且他们的 GCS JAVA api 在 Android 中不起作用(GcsService 服务 = GcsServiceFactory.createGcsService() ;).似乎他们希望您只能从 App 引擎访问 GCS。

所以,这是我们需要做的:

  • 您可能不希望用户必须登录 GCS 或 Google(想想 Snapchat 应用)。
  • 但是您仍然需要身份验证,因此您的数据不会完全公开;它只能通过您的应用访问。
  • 您需要一个服务帐户 P2K 文件,您可以将其与应用程序 bundle 在一起,这样您的用户就无需在任何地方登录。
  • 来自 https://cloud.google.com/console/project ,单击“项目”>“API 和授权”>“凭据”>“创建新的客户端 ID”>“服务帐户”。这会让您下载 P2K 文件。
  • 将其存储在 res/raw/private_key.p2k 中,然后使用以下代码验证您的 Android 应用以查询 GCS。

这对我来说没有任何问题:

        String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
        JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

        Log.d("testing", "checking if I can create a credential");
        httpTransport = AndroidHttp.newCompatibleTransport();
        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(resources_.openRawResource(R.raw.gcs_privatekey),
                "password".toCharArray());

        PrivateKey key = (PrivateKey) keystore.getKey("privatekey", "password".toCharArray());

        GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountPrivateKey(key)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
                // .setServiceAccountUser(SERVICE_ACCOUNT_EMAIL)
                // .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
                .build();
        credential.refreshToken();

        String URI = "https://storage.googleapis.com/" + BUCKET_NAME;
        HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
        GenericUrl url = new GenericUrl(URI);
        HttpRequest request = requestFactory.buildGetRequest(url);
        HttpResponse response = request.execute();
        String content = response.parseAsString();
        Log.d("testing", "response content is: " + content);
        new Storage.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName("appname").build();

关于android - 从 Android OAuth2 访问谷歌云存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12131044/

有关android - 从 Android OAuth2 访问谷歌云存储的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  6. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  7. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  8. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

  9. ruby - 从外部访问类的实例变量 - 2

    我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内

  10. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

随机推荐