【发布时间】:2019-10-17 06:32:18
【问题描述】:
你好 stackoverflow 社区,
我正在为我正在进行的测试项目使用 Firestore,而不是实时数据库。
- 作为初学者,我正在尝试在现有集合和项目中创建一个新文档,该集合和项目是我通过 Web 界面手动创建的。我的项目 id 是
newproject-30f72,已经创建的集合名称是testcollection。 - 我开启了
Email/Password认证方式,并注册了一个新的email-id/password用户。我对启用身份验证的写入的规则如下。
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
此时,我不确定,仅在标头中传递的裸令牌就足以验证request.auth.uid != null,所以很可能我的规则也可能是错误的,因为我使用模拟器自动生成规则,但我通过完全禁用规则验证了该规则不会导致我目前面临的问题。
- 我启用了
rules,这样只有经过身份验证的用户才能写入firestore。 (通过身份验证,我指的是基于特定email/password用户的idToken,而不是网络应用程序的apiKey。我不知道这是否可能。) - 我启用了
Add Firebase to your web app / register app,这给了我一个名为firebaseConfig的json 对象,其中包含以下详细信息。
var firebaseConfig = {
apiKey: "some_api_key",
authDomain: "newproject-30f72.firebaseapp.com",
databaseURL: "https://newproject-30f72.firebaseio.com",
projectId: "newproject-30f72",
storageBucket: "newproject-30f72.appspot.com",
messagingSenderId: "111122223333",
appId: "1:1111:web:2222"
};
我正在使用上述 json 对象中的 apiKey 来获取在一段时间内有效的 idToken,以写入 firestore 数据库。 python3中的代码如下。
import json
from urllib import request, error
from collections import defaultdict
firebase_apikey = 'some_api_key'
auth_request_url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key={}".format(firebase_apikey)
class auth:
def __init__(self, email: str, password: str):
self.email = email
self.password = password
self.post_data = defaultdict()
self.post_data['email'] = self.email
self.post_data['password'] = self.password
self.post_data['returnSecureToken'] = True
self.headers = {"Content-Type": "application/json"}
# print("POST DATA IS:: " + json.dumps(self.post_data))
self.r = request.Request(auth_request_url,
data=json.dumps(self.post_data).encode(),
headers=self.headers)
# self.url_open
def get_auth_token(self):
try:
self.url_open = request.urlopen(self.r)
except Exception as e:
return e
try:
return json.loads(self.url_open.read())
except Exception as e:
return e
s = auth("someuser.somethingelse@gmail.com", "somepassword")
response = s.get_auth_token()
id_token = response['idToken']
expires_in = response['expiresIn']
我得到了 idToken,它是一个 924 字符长的字符串。
现在我正在尝试使用Authorization': 'Bearer 标头向firestore 写入我收到的idToken,并且有效期为3600(我认为是秒),如下所示。
firestore_project_url = "https://firestore.googleapis.com/v1beta1/projects/{}/databases/(default)/documents:write".format(
'newproject-30f72')
headers = {
'Content-type': 'application/json',
'Authorization': 'Bearer %s' % id_token,
}
test_data = '''
{
"writes": [{
"updateMask": {
"fieldPaths": ["name"]
},
"update": {
"name": "projects/newproject-30f72/databases/(default)/documents/testcollection/testdoc/",
"fields": {
"name": {
"stringValue": "test"
}
}
}
}]
}
'''
test_data_json_bytes = json.dumps(test_data).encode("utf-8")
req = request.Request(url=firestore_project_url,
data=test_data_json_bytes,
headers=headers,
method='POST')
print(headers)
f = request.urlopen(req)
我可以看到标题为
{'Content-type': 'application/json', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsI........<snip>'}
但我收到 urllib.error.HTTPError: HTTP Error 400: Bad Request 错误。
我指的是 Firebase Firestore REST example 使用带有自定义标头的 curl 检查它以添加不记名令牌并查看是否有任何可能的冗长,我看到了
* Trying 74.125.68.95...
* TCP_NODELAY set
* Connected to firestore.googleapis.com (74.125.68.95) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=*.googleapis.com
* start date: May 14 13:35:00 2019 GMT
* expire date: Aug 6 13:20:00 2019 GMT
* subjectAltName: host "firestore.googleapis.com" matched cert's "*.googleapis.com"
* issuer: C=US; O=Google Trust Services; CN=Google Internet Authority G3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x560e5884af30)
> POST /v1beta1/projects/newproject-30f72/databases/(default)/documents/testcollection3 HTTP/2
> Host: firestore.googleapis.com
> User-Agent: curl/7.64.1
> Accept: */*
> {Content-type: application/json, Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6........<snip>}
> Content-Type: application/json
> Content-Length: 258
>
* We are completely uploaded and fine
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 400
< content-type: text/html; charset=UTF-8
< referrer-policy: no-referrer
< content-length: 1555
< date: Fri, 31 May 2019 14:31:36 GMT
<
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
* Connection #0 to host firestore.googleapis.com left intact
curl: (92) HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* Closing connection 0
我指的是以下链接以供参考。
https://groups.google.com/forum/#!topic/google-cloud-firestore-discuss/4Le2RskC3cg https://firebase.google.com/docs/firestore/reference/rest/v1beta1/projects.databases.documents/commit
我想要实现的是
- 使用电子邮件/密码身份验证通过 Firestore 进行身份验证
- 创建集合并向其写入文档。
非常感谢任何帮助。
非常感谢。
【问题讨论】:
-
有什么理由不使用 firebase-admin?
-
我也可以使用 firebase-admin,但我找不到使用电子邮件 ID/密码身份验证(不使用 oauth 或 json 密钥文件)使用 idToken 登录的文档参考。非常感谢任何有关身份验证和进一步 CRUD 操作的参考或示例代码。谢谢@Will
-
好吧,如果客户传递给你 idToken 然后使用Firebase Admin。如果您的客户给您电子邮件/密码,请使用REST API。我用的是后者。
-
啊,抱歉没有正确理解这个问题。您希望 Firestore 加入其规则,因为您基本上是在模拟用户?
-
好的,我已经使用
Authorization: Bearer <idtoken>测试了一个 GET,它工作正常。 400 错误意味着您身上的某些东西有问题。您是否测试过集合上的简单 GET 与 auth 一起使用的方式是否通过了您的方式?
标签: python python-3.x firebase rest google-cloud-firestore