我正在尝试使用谷歌云存储的JSON API从谷歌云存储中检索文件。我不允许使用SDK。是否可以从ServiceAccount.json文件创建JWT并使用JWT从Google云存储访问文件?我在node.js中有一个脚本,可以从服务帐户生成JWT,但我不确定受众是否正确
const jwt = require('jsonwebtoken');
const serviceAccount = require('./serviceAccount.json');
const issuedAt = Math.floor(Date.now() / 1000);
const TOKEN_DURATION_IN_SECONDS = 3600;
let params = {
'iss': serviceAccount.client_email,
'sub': serviceAccount.client_email,
'aud': serviceAccount.project_id,
'iat': issuedAt,
'exp': issuedAt + TOKEN_DURATION_IN_SECONDS,
};
let options = {
algorithm: 'RS256',
header: {
'kid': serviceAccount.private_key_id,
'typ': 'JWT',
'alg': 'RS256',
},
};
let token = jwt.sign(params, serviceAccount.private_key, options);
console.log(token);
然后,我使用该JWT调用Google云存储JSON API:
https://www.googleapis.com/storage/v1/b/test
使用标头:授权承载{token}
这只会导致无效凭据的响应。
有几个问题:
我不确定创建JWT时“aud”应该是什么。我见过一些例子,其中它是一个url,也有一个projectId。都不适合我。
- 其中一个JSONAPI示例说授权令牌应该是oauth令牌。我可以改用JWT吗?还是需要使用JWT打电话来获取访问令牌?
- 我的铲斗路径正确吗?bucket路径的基本文件夹是您的projectId吗?我的路径应该是
/{projectId}/test
。我两个都试过,两个都没试过
扼要重述
这是一个物联网项目,我需要嵌入式设备从谷歌云存储下载文件。我需要创建一个Web门户来上传文件(使用Firebase功能),并将桶路径或私有/签名URL传递给设备。底线是我需要使用服务号密钥访问谷歌云存储桶。如果有嵌入式SDK-太好了,但是我找不到C的SDK。我唯一的想法是使用JSON API。如果有一种方法,我可以签署一个只能使用服务号访问的网址-那也可以。
谢谢
是的,您可以从服务帐户Json(或P12)文件创建自己的签名JWT,并将JWT交换为访问令牌,然后将其用作授权:承载令牌
我已经写了很多关于如何使用Json和P12凭据的文章。
Google Cloud–为REST API调用创建OAuth访问令牌
对于您的问题:
我不确定创建JWT时“aud”应该是什么。我见过一些例子,其中它是一个url,也有一个projectId。两个都不适合我。
设置aud
为"https://www.googleapis.com/oauth2/v4/token"
其中一个JSON API示例说授权令牌应该是一个oauth令牌。我可以使用JWT代替,还是需要使用JWT打电话来获得访问令牌?
一些API接受签名的JWT,其他API则期望OAuth访问令牌。总是获得OAuth访问令牌更容易。在我下面的示例代码中,我向您展示了如何。
我的铲斗路径正确吗?bucket路径的基本文件夹是您的projectId吗?我的路径应该是/{projectId}/test。我两个都试过,两个都没试过。
你的url应该像这样(Python字符串构建示例)
url = "https://www.googleapis.com/storage/v1/b?project=" + project
下面我将向您展示如何呼叫两个服务(GCE和GCS)。大多数GoogleAPI将遵循类似的样式来构建RESTAPI URL。
从问题中的代码来看,您缺少OAuth过程中的最后一步。您需要将已签名的JWT交换为访问令牌。
def exchangeJwtForAccessToken(signed_jwt):
'''
This function takes a Signed JWT and exchanges it for a Google OAuth Access Token
'''
auth_url = "https://www.googleapis.com/oauth2/v4/token"
params = {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt
}
r = requests.post(auth_url, data=params)
if r.ok:
return(r.json()['access_token'], '')
return None, r.text
下面是一个完整的Python3.x示例,它将列出GCE实例。此代码下面是显示GCS存储桶的更改。
'''
This program lists lists the Google Compute Engine Instances in one zone
'''
import time
import json
import jwt
import requests
import httplib2
# Project ID for this request.
project = 'development-123456'
# The name of the zone for this request.
zone = 'us-west1-a'
# Service Account Credentials, Json format
json_filename = 'service-account.json'
# Permissions to request for Access Token
scopes = "https://www.googleapis.com/auth/cloud-platform"
# Set how long this token will be valid in seconds
expires_in = 3600 # Expires in 1 hour
def load_json_credentials(filename):
''' Load the Google Service Account Credentials from Json file '''
with open(filename, 'r') as f:
data = f.read()
return json.loads(data)
def load_private_key(json_cred):
''' Return the private key from the json credentials '''
return json_cred['private_key']
def create_signed_jwt(pkey, pkey_id, email, scope):
'''
Create a Signed JWT from a service account Json credentials file
This Signed JWT will later be exchanged for an Access Token
'''
# Google Endpoint for creating OAuth 2.0 Access Tokens from Signed-JWT
auth_url = "https://www.googleapis.com/oauth2/v4/token"
issued = int(time.time())
expires = issued + expires_in # expires_in is in seconds
# Note: this token expires and cannot be refreshed. The token must be recreated
# JWT Headers
additional_headers = {
'kid': pkey_id,
"alg": "RS256",
"typ": "JWT" # Google uses SHA256withRSA
}
# JWT Payload
payload = {
"iss": email, # Issuer claim
"sub": email, # Issuer claim
"aud": auth_url, # Audience claim
"iat": issued, # Issued At claim
"exp": expires, # Expire time
"scope": scope # Permissions
}
# Encode the headers and payload and sign creating a Signed JWT (JWS)
sig = jwt.encode(payload, pkey, algorithm="RS256", headers=additional_headers)
return sig
def exchangeJwtForAccessToken(signed_jwt):
'''
This function takes a Signed JWT and exchanges it for a Google OAuth Access Token
'''
auth_url = "https://www.googleapis.com/oauth2/v4/token"
params = {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt
}
r = requests.post(auth_url, data=params)
if r.ok:
return(r.json()['access_token'], '')
return None, r.text
def gce_list_instances(accessToken):
'''
This functions lists the Google Compute Engine Instances in one zone
'''
# Endpoint that we will call
url = "https://www.googleapis.com/compute/v1/projects/" + project + "/zones/" + zone + "/instances"
# One of the headers is "Authorization: Bearer $TOKEN"
headers = {
"Host": "www.googleapis.com",
"Authorization": "Bearer " + accessToken,
"Content-Type": "application/json"
}
h = httplib2.Http()
resp, content = h.request(uri=url, method="GET", headers=headers)
status = int(resp.status)
if status < 200 or status >= 300:
print('Error: HTTP Request failed')
return
j = json.loads(content.decode('utf-8').replace('\n', ''))
print('Compute instances in zone', zone)
print('------------------------------------------------------------')
for item in j['items']:
print(item['name'])
if __name__ == '__main__':
cred = load_json_credentials(json_filename)
private_key = load_private_key(cred)
s_jwt = create_signed_jwt(
private_key,
cred['private_key_id'],
cred['client_email'],
scopes)
token, err = exchangeJwtForAccessToken(s_jwt)
if token is None:
print('Error:', err)
exit(1)
gce_list_instances(token)
要显示GCS桶,请修改代码:
# Create the HTTP url for the Google Storage REST API
url = "https://www.googleapis.com/storage/v1/b?project=" + project
resp, content = h.request(uri=url, method="GET", headers=headers)
s = content.decode('utf-8').replace('\n', '')
j = json.loads(s)
print('')
print('Buckets')
print('----------------------------------------')
for item in j['items']:
print(item['name'])
我正在实现一个需要身份验证的REST服务。我正在使用JWT。 现在,Android应用程序在登录时发送一个请求,获得一个令牌,并且必须在每个后续请求的头中发送令牌。 我的问题是,如何存储令牌,或者我应该将其存储在哪里? 共享偏好 SQLite数据库 归档 最好的做法是什么?还是我完全错了?
我正在用Django和angular构建一个应用程序。目前,我正在本地存储上存储后端发布的JWT。但是,我担心XSS攻击。我应该使用仅HTTP cookie存储令牌吗?我还考虑将令牌存储在auth服务类的变量字段中。但我不能完全确定angular是否在整个应用程序中共享该服务。我的身份验证服务是否只有一个实例?
是否可以使用来自Google API客户端Javascript库的承载令牌来授权Google云存储桶,而无需向用户请求https://www.googleapis.com/auth/devstorage范围。该桶具有对所有Google帐户的读写访问权限。
Stormpath 中有很多博客文章讨论了您应该如何使用 cookie 而不是 sessionStorage/localStorage 来存储您的 JWT: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage https://stormpath.com/blog/token-auth-sp
我正在学习谷歌云存储,JSON api,简单上传: https://cloud.google.com/storage/docs/json_api/v1/how-tos/simple-upload 示例显示发送一篇如下所示的帖子: 然后我创建了一个“服务帐户”应用编程接口。 但是我如何从我新创建的服务帐户中找到要使用的?
我正在使用vue.js和vuex开发一个应用程序,它使用JWT令牌对JSON API服务器进行身份验证。所以我想知道存放JWT代币的最佳做法是什么? 如果我将其存储在vuex商店中,则页面刷新后它会丢失,因此用户需要再次登录,这不是很方便。 如果我将其存储在浏览器的本地存储中,它会在下次登录之前被弃用,然后假设身份验证令牌的组件会混淆。我不知道如何处理这个问题。 感谢你对此的暗示。