Java Google 推送通知 - 未经授权的 WebHook 回调通道
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23928758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google push notifications - Unauthorized WebHook callback channel
提问by user3686724
I'm facing problem with Google push notifications (for drive). I use service account which works perfectly for all other drive operations except drive changes watch.
我遇到了 Google 推送通知(驱动器)的问题。我使用的服务帐户适用于除驱动器更改手表之外的所有其他驱动器操作。
Below is application code which now fails with "Unauthorized WebHook callback channel" exception. I also dumped requests and responses which are generated when drive.changes.watch.execute is called.
以下是现在因“未经授权的 WebHook 回调通道”异常而失败的应用程序代码。我还转储了调用 drive.changes.watch.execute 时生成的请求和响应。
Target notification address is whitelisted in APIs & auth Push control panel (I even listed it in Javascript origins and referrers) and now I'm stuck with this 401 Unauthorized error.
目标通知地址在 APIs & auth Push 控制面板中被列入白名单(我什至在 Javascript origins 和 referrers 中列出了它),现在我被这个 401 Unauthorized 错误所困扰。
Does someone know where I'm making mistake? Thanks for any help.
有人知道我哪里出错了吗?谢谢你的帮助。
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), p12File, "notasecret", "privatekey", "notasecret");
JsonFactory jsonFactory = new HymansonFactory();
HttpTransport t = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential gc = new GoogleCredential.Builder()
.setTransport(t)
.setJsonFactory(jsonFactory)
.setServiceAccountScopes(Collections.singleton(DriveScopes.DRIVE))
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.setServiceAccountId(Config.SERVICE_ACCOUNT_ID)
.setServiceAccountUser(Config.SERVICE_ACCOUNT_USER)
.build();
drive = new Drive.Builder(t, jsonFactory, null).setHttpRequestInitializer(gc).setApplicationName(cfg.getStringParam(Config.GAE_APPLICATION_NAME)).build();
// THIS WORKS
Changes.List request = drive.changes().list();
ChangeList changes = request.execute();
// THIS DOES NOT WORK
Channel channel = new Channel();
channel.setId(UUID.randomUUID().toString());
channel.setType("web_hook");
channel.setAddress(Config.PUSH_NOTIFICATION_ADDRESS);
Channel c = drive.changes().watch(channel).execute();
-------------- REQUEST --------------
POST https://www.googleapis.com/drive/v2/changes/watch
Accept-Encoding: gzip
Authorization: Bearer XXX
User-Agent: XXX Google-HTTP-Java-Client/1.17.0-rc (gzip)
Content-Type: application/json; charset=UTF-8
Content-Length: 118
CONFIG: curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'Authorization: Bearer XXX' -H 'User-Agent: XXX Google-HTTP-Java-Client/1.17.0-rc (gzip)' -H 'Content-Type: application/json; charset=UTF-8' -d '@-' -- 'https://www.googleapis.com/drive/v2/changes/watch' << $$$
CONFIG: {"address":"XXX","id":"8078114c-fba0-44e7-a34c-cb391ea40061","type":"web_hook"}
-------------- RESPONSE --------------
401 OK
www-authenticate: Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token
-------------- REQUEST --------------
POST https://accounts.google.com/o/oauth2/token
-------------- RESPONSE --------------
200 OK
{
"access_token" : XXX,
"token_type" : "Bearer",
"expires_in" : 3600
}
-------------- REQUEST --------------
POST https://www.googleapis.com/drive/v2/changes/watch
-------------- RESPONSE --------------
401 OK
www-authenticate: Bearer realm="https://accounts.google.com/AuthSubRequest", error=invalid_token
...
...
...
-------------- RESPONSE --------------
200 OK
content-type: application/json; charset=utf-8
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: Fri, 01 Jan 1990 00:00:00 GMT
date: Wed, 28 May 2014 20:51:19 GMT
content-disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
content-encoding: gzip
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
server: GSE
alternate-protocol: 443:quic
transfer-encoding: chunked
{
"access_token" : XXX,
"token_type" : "Bearer",
"expires_in" : 3600
}
{
"error": {
"errors": [
{
"domain": "global",
"reason": "push.webhookUrlUnauthorized",
"message": "Unauthorized WebHook callback channel: XXX"
}
],
"code": 401,
"message": "Unauthorized WebHook callback channel: XXX"
}
}
回答by natronite
You have to add your domain to the developers console.
您必须将您的域添加到开发人员控制台。
How to:
如何:
- Log in to the Google Developers Console
- Select your project
- Under 'APIS & AUTH' select 'Push'
- Click 'Add domains'
- Enter the needed domains (Only the domain is needed, not the whole notification url)
- Click the 'Add domains' button
- 登录Google Developers Console
- 选择您的项目
- 在“APIS & AUTH”下选择“推送”
- 点击“添加域”
- 输入需要的域名(只需要域名,不需要整个通知网址)
- 单击“添加域”按钮
After that it should work unless there's something else wrong with what you're doing :p
之后它应该可以工作,除非你正在做的事情有其他问题:p
回答by John Naegle
For me, as I put in a comment above,
对我来说,正如我在上面的评论中所说的那样,
The Domain Verification was not saving in google developer console (refresh the page and it was gone). The problem ultimately ended up being I was logged in as two google accounts, my gmail account and my company account. Adding the domain verification seemed to get confused about the account and not save the domain settings.
域验证没有保存在谷歌开发者控制台中(刷新页面,它不见了)。问题最终导致我以两个谷歌帐户登录,我的 gmail 帐户和我的公司帐户。添加域验证似乎对帐户感到困惑,而不是保存域设置。
Try logging in using a different browser or incognito session if you use multiple google accounts.
如果您使用多个 google 帐户,请尝试使用不同的浏览器或隐身会话登录。
回答by Aniket Thakur
For me, I wanted the callback webhook URL as https://test-apis.domain.io
. So for domain verification, I added test-apis.domain.io
and then tried to modify the TXT record but it never was working(validating).
对我来说,我希望回调 webhook URL 为https://test-apis.domain.io
. 因此,对于域验证,我添加test-apis.domain.io
并尝试修改 TXT 记录,但它从未起作用(正在验证)。
Finally ended up verifying just domain.io
with the same method. After this was done I was able to add the domain test-apis.domain.io
in the credentials "Domain verification" screen. Hope this helps others as well.
最后只domain.io
用同样的方法进行验证。完成此操作后,我可以test-apis.domain.io
在凭据“域验证”屏幕中添加域。希望这对其他人也有帮助。
回答by Artemius Pompilius
I confirmed my domain, checked my SSL, but problem hasn't gone.
我确认了我的域,检查了我的 SSL,但问题并没有消失。
Finally I found the solution: Use Service Acconut Keyin Google Developers Console (not API Key and not OAuth client ID).
最后我找到了解决方案:在 Google Developers Console 中使用服务帐户密钥(不是 API 密钥,也不是 OAuth 客户端 ID)。
回答by Munkhbayar Nergui
So this is all because of Settings on console.developers.google.com. You need to add your back-end domain to both Authorised domains on (OAuth Consent Screen tab) and Allowed domains (on Domain Verification tab).
所以这完全是因为 console.developers.google.com 上的设置。您需要将后端域添加到授权域(OAuth 同意屏幕选项卡)和允许域(在域验证选项卡上)。
So there reason why it works for you now is that probably you verified and added your top-level domain already while your local environment had separate (not a sub domain of the verified top-level) domain at the time, specially if you had been exposing your local server on internet.
所以它现在对你有用的原因是你可能已经验证并添加了你的顶级域,而你的本地环境当时有单独的(不是已验证顶级域的子域)域,特别是如果你已经在互联网上公开您的本地服务器。
回答by Picrasma
NONE OF THESE WORKED! nothing works
这些都没有用!没有任何效果