유니코드 사용자 이름

현재 Discourse의 유니코드 사용자 이름이 API와 함께 작동하지 않습니다.

이 버그를 수정할 수 있을까요?

방금 이걸 시도해 보았는데 제 환경에서는 작동합니다:

○ → curl -s -L -H 'api-key: «redacted»' -H 'api-username: doesnotexist' https://try.discourse.org/u/运思/notifications.json
{"errors":["You are not permitted to view the requested resource. The API username or key is invalid."],"error_type":"invalid_access"}

○ → curl -s -L -H 'api-key: «redacted»' -H 'api-username: 运思' https://try.discourse.org/u/运思/notifications.json | jq '.users[0]'
{
  "id": 41,
  "username": "运思",
  "name": "Michael Brown",
  "avatar_template": "/user_avatar/try.discourse.org/运思/{size}/208_2.png",
  "trust_level": 1,
  "assign_icon": "user-plus",
  "assign_path": "/u/运思/activity/assigned"
}

어떻게 실패하는지 시연해 주시겠어요?

Michael Brown 님, 감사합니다.

테스트해 보았더니 브라우저에서는 문제가 없었지만, 프로그래밍 소프트웨어에서는 오류가 발생합니다. 이는 해당 프로토콜을 전송할 때 ASCII만 사용해야 한다는 규칙 때문이죠.

오류 발생 원인:

TypeError: Invalid character in header content [“Api-Username”]

로그를 확인해 주시고, 매칭을 위해 utf8 인코딩 또는 디코딩을 한 번 추가하는 것이 권장됩니다.

  1. 테스트 인터페이스

  1. 웹 주소

https://xxxxxxxx/posts.json

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:system

테스트 결과:

OK

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:风之旅人

{“status”:500,“error”:“Internal Server Error”}

Accept:application/json
api-key:f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username:%E8%BF%90%E6%80%9D

요청한 리소스를 볼 권한이 없습니다. API 사용자 이름 또는 키가 유효하지 않습니다

오류 원인:

헤더에서 중국어를 사용하는 것은 유효하지 않으며, 서버로 전송하려면 encodeURI()로 인코딩해야 합니다. 또한 서버가 이를 인식하려면 decodeURI()로 디코딩해야 합니다.

판단 로직을 추가하는 것을 제안합니다. 찾지 못한 경우 decodeURI를 시도하여 사용자 이름을 매칭하도록 하세요.

무엇을 사용 중이신가요? 오류가 Python처럼 보입니다. requests에서는 지원되지만, 사용 중인 라이브러리에서는 지원되지 않을 수 있습니다.

In [1]: import requests

In [2]: api_key = '«redacted»'

In [3]: r = requests.get('https://try.discourse.org/u/运思/notifications.json', headers = {
  'api-key': api_key,
  'api-username': '运思'.encode()
})

In [4]: r.status_code
Out[4]: 200

In [5]: r.json()['users'][0]
Out[5]: 
{'id': 41,
 'username': '运思',
 'name': 'Michael Brown',
 'avatar_template': '/user_avatar/try.discourse.org/运思/{size}/208_2.png',
 'trust_level': 1,
 'assign_icon': 'user-plus',
 'assign_path': '/u/运思/activity/assigned'}

헤더 값을 명시적으로 bytes로 변환하기 위해 .encode()를 호출해 보세요… 다만 모든 것이 8비트 클린하지는 않으므로, 이 제안에 동의합니다:

이 제안은 합리적입니다.

포럼에서 검색하기. 이전 버전의 API는 Query와 함께 사용할 수 있습니다.

새로운 버전의 API는 Query와 함께 작동하지 않습니다.

Query와 호환되는지 확인하고 이 문제를 수정하십시오.

예시:

https://www.xxx.com/posts.json?api_key=714552c6148e1617aeab526d0606184b94a80ec048fc09894ff1a72b740c5f19&api_username=system

이 문제가 해결되기를 바랍니다.

해결되지 않을 겁니다. 이제 API 파라미터를 쿼리 파라미터 대신 헤더로 전달해야 합니다. 이 부분은 변경되지 않습니다.

하지만 헤더에는 비 ASCII 문자를 전달할 수 없으며, 중국어 사용자 이름을 전달하고 싶습니다.

아래 @supermathie의 증명처럼 가능합니다:

cURL

Python:

사실 작동하지 않습니다. 제가 시도해 봤는데, 헤더에는 비-ASCII 문자를 포함할 수 없으므로 인코딩 변환이 필요합니다. 하지만 문자를 인코딩한 후에는 사용자가 존재하지 않는다는 메시지가 표시됩니다. 이는 수신 측인 Discourse에서 복원(디코딩)을 하지 않기 때문입니다!!

헤더는 URI 인코딩이 아니라 UTF-8로 인코딩되어야 합니다.

  1. 1: 헤더에는 중국어 문자를 사용할 수 없습니다.
  2. 2: utf8은 포스트의 내용을 가리키는 것이며, 헤더를 가리키는 것이 아닙니다.
  3. 3: Discourse는 UrlEncode로 디코딩하지 않으므로, 해당 사용자 이름이 존재하지 않는다고 표시됩니다.

아래와 같은 테스트 데이터를 제공합니다

https://www.baowei.ink/posts.json
{
  "title": "标题标题标题标题标题",
  "raw": "标题标题标题标题标题标题标题标题标题标题",
  "category": 10,
}

성공

Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: system

실패

Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: 风之旅人
Content-Type: application/json; charset=UTF-8
Api-Key: «redacted»
Api-Username: %E9%A3%8E%E4%B9%8B%E6%97%85%E4%BA%BA

감사합니다! Michael Brown

zengyunsi님, 해당 API 키를 즉시 회전(교체)하셔야 합니다. 이미 유출된 것으로 간주하세요.

… 다만 헤더를 UTF-8로 인코딩하면 동작하는 것을 확인했습니다:

In [1]: import requests

In [2]: api_key = '«redacted»'

In [3]: r = requests.get('https://www.baowei.ink/posts.json', headers={'api-key': api_key, 'api-username': '风之旅人'.encode()})

In [4]: r.status_code
Out[4]: 200

In [5]: len(r.json()['latest_posts'])
Out[5]: 19

이것이 해당 사항인지, 예시를 제공해 주실 수 있을까요? 감사합니다!

Content-Type: Application/json; charset=utf-8
Accept: Application/json; charset=utf-8
Api-Key: f9c13aafa9b21baf778161bff66a62533ba650b6e4542e3e9788e98c55ded869
Api-Username: \xe9\xa3\x8e\xe4\xb9\x8b\xe6\x97\x85\xe4\xba\xba

항상 프롬프트
요청한 리소스를 볼 권한이 없습니다. API 사용자 이름 또는 키가 유효하지 않습니다.

아래 예제가 작동하는 것을 확인했습니다:

$ curl -s -L \
-H 'api-key: 60834ccb8eda28cf17bab8efbbb2fbf874eb8b5a75ff17ddbd2346eb292881a0' \
-H 'api-username: 测试用户' \
http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json

{"email":"discobot_email","secondary_emails":[],"unconfirmed_emails":[],"associated_accounts":[]}

그리고 api-* 헤더 없이 요청하면:

$ curl -s -L \
http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json

{"errors":["You need to be logged in to do that."],"error_type":"not_logged_in"}

Python requests 예제:

import requests

api_key = '60834ccb8eda28cf17bab8efbbb2fbf874eb8b5a75ff17ddbd2346eb292881a0'
api_username = '测试用户'
api_endpoint = 'http://localhost:4200/u/%E6%B5%8B%E8%AF%95%E7%94%A8%E6%88%B7/emails.json'

r = requests.get(api_endpoint, headers={
                 'api-key': api_key, 'api-username': api_username.encode()})

print(r)

<Response [200]>

api-username 값이 적절하게 인코딩되지 않는 것 같습니다.

>>> '风之旅人'.encode()
b'\xe9\xa3\x8e\xe4\xb9\x8b\xe6\x97\x85\xe4\xba\xba'

https://stackoverflow.com/questions/6269765/what-does-the-b-character-do-in-front-of-a-string-literal

모두 감사합니다. 한 번 시도해 보겠습니다. 중국어 사용자 이름으로 API 작업을 호출하는 것이 더 편리하다면, 감사합니다!


이건 좀 이상하고, API도 정상적으로 사용할 수 없어요

API 키의 범위에 문제가 있을 가능성이 높습니다.

:sweat_smile: 시도해 봤는데 역시 안 되네요. 다만 저는 Python을 몰라서요.
같은 메시지가 뜨네요··

ASCII 사용자 이름으로 동일한 호출이 작동하나요?

(아니라고 추측하며, 그것이 "API를 정상적으로 사용할 수 없다"는 말씀의 의미라고 생각합니다.)

그렇다면 웹사이트 앞에 다른 프록시가 있는지, 아니면 표준 설치를 사용 중인가요?

네, 이 호출은 바이트 자체 대신 UTF-8 바이트 시퀀스의 이스케이프 표현으로 인코딩했습니다.