英文:
Ghost CMS API from R
问题
我正在尝试使用内置的 Admin API 从 R 连接到本地的 Ghost CMS 实例。有一份很好的文档 (https://ghost.org/docs/admin-api/#token-authentication),介绍了如何在各种编程语言中进行连接,但不幸的是没有提供 R 的说明。我已经编写了以下代码,但在尝试创建测试文章时不幸收到了 401 错误。非常感谢任何帮助。
R 代码:
api_admin_key <-
"xxxxxx:yyyyyyyyyyyyyyy"
api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
names(api_admin_key) <- c("id", "secret")
# 准备头部和负载
iat <- as.integer(Sys.time())
header <-
list(alg = 'HS256', typ = 'JWT', kid = api_admin_key[["id"]])
# 创建令牌(包括解码密钥)
payload <-
jose::jwt_claim(iat = iat,
exp = iat + 5 * 60,
aud = '/admin/')
token <-
jose::jwt_encode_hmac(
claim = payload,
secret = charToRaw(api_admin_key[["secret"]]),
size = 256,
header = header
)
# 发送经过身份验证的请求以创建文章
url <- 'http://localhost:2368/ghost/api/admin/posts/'
headers <- c('Authorization' = paste("Ghost", token))
body <- list(posts = list(
"title" = 'Hello World',
"html" = "<p>My post content. Work in progress...</p>",
"status" = "published"
)
)
httr::POST(url,
body = body,
encode = "json",
httr::add_headers(.headers = headers))
<details>
<summary>英文:</summary>
I am trying to connect to a local Ghost CMS instance from __R__ using the build-in Admin API. There is a good documentation ([https://ghost.org/docs/admin-api/#token-authentication][1]) on how to connect for various languages but unfortunately not for __R__. I have compiled the following code but unfortunately receive a 401 error when trying to create a test post. Any help is much appreciated.
__R__ code:
api_admin_key <-
"xxxxxx:yyyyyyyyyyyyyyy"
api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
names(api_admin_key) <- c("id", "secret")
# Prepare header and payload
iat <- as.integer(Sys.time())
header <-
list(alg = 'HS256', typ = 'JWT', kid = api_admin_key[["id"]])
# Create the token (including decoding secret)
payload <-
jose::jwt_claim(iat = iat,
exp = iat + 5 * 60,
aud = '/admin/')
token <-
jose::jwt_encode_hmac(
claim = payload,
secret = charToRaw(api_admin_key[["secret"]]),
size = 256,
header = header
)
# Make an authenticated request to create a post
url <- 'http://localhost:2368/ghost/api/admin/posts/'
headers <- c('Authorization' = paste("Ghost", token))
body <- list(posts = list(
"title" = 'Hello World',
"html" = "<p>My post content. Work in progress...</p>",
"status" = "published"
)
)
httr::POST(url,
body = body,
encode = "json",
httr::add_headers(.headers = headers))
[1]: https://ghost.org/docs/admin-api/#token-authentication
</details>
# 答案1
**得分**: 2
看起来问题出在你传递给 `jwt_encode_hmac()` 的 `secret=` 参数上。`charToRaw` 函数不能理解十六进制数字。它只使用ASCII字符代码。要进行转换,你需要使用来自[这个现有问题](https://stackoverflow.com/questions/70884796/convert-hexadecimal-string-to-bytes-in-r)的其中一个 `hex_to_raw` 函数。我将在这里使用一个:
```R
hex_to_raw <- function(x) {
digits <- strtoi(strsplit(x, "")[[1]], base=16L)
as.raw(bitwShiftL(digits[c(TRUE, FALSE)],4) + digits[c(FALSE, TRUE)])
}
此外,你不需要在头部指定 alg 和 typ,因为这些信息将由函数自动添加。所以你可以使用以下方式构建你的令牌:
api_admin_key <- "adam:12bd18f2cd12"
api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
names(api_admin_key) <- c("id", "secret")
# 准备头部和负载
iat <- as.integer(Sys.time())
header <- list(kid = api_admin_key[["id"]])
# 创建令牌(包括解码密钥)
payload <-
jose::jwt_claim(iat = iat,
exp = iat + 5 * 60,
aud = '/admin/')
token <-
jose::jwt_encode_hmac(
claim = payload,
secret = hex_to_raw(api_admin_key[["secret"]]),
size = 256,
header = header
)
我使用了 https://jwt.io/ 上的调试器测试了每个令牌,它们似乎是等效的。在调试器中,十六进制值 "12bd18f2cd12" 的 base64 编码值是 "Er0Y8s0S"。
英文:
It looks like the problem is the secret=
you are passing to jwt_encode_hmac()
. The charToRaw
doesn't understand hex digits. It's just using the ascii character codes. To do the translation, you'd need one of the hex_to_raw
functions from this existing question. I'll use one here
hex_to_raw <- function(x) {
digits <- strtoi(strsplit(x, "")[[1]], base=16L)
as.raw(bitwShiftL(digits[c(TRUE, FALSE)],4) + digits[c(FALSE, TRUE)])
}
Also, you don't need to specify the alg and typ in the header because those are added by the function, So you would build your token with
api_admin_key <- "adam:12bd18f2cd12"
api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
names(api_admin_key) <- c("id", "secret")
# Prepare header and payload
iat <- as.integer(Sys.time())
header <- list(kid = api_admin_key[["id"]])
# Create the token (including decoding secret)
payload <-
jose::jwt_claim(iat = iat,
exp = iat + 5 * 60,
aud = '/admin/')
token <-
jose::jwt_encode_hmac(
claim = payload,
secret = hex_to_raw(api_admin_key[["secret"]]),
size = 256,
header = header
)
I tested each of the tokens using the debugger at https://jwt.io/ and they seemed equivalant. Using the debugger, the base64 encoded value for the hexvalue "12bd18f2cd12" is "Er0Y8s0S"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论