Ghost CMS API 来自 R

huangapple go评论115阅读模式
英文:

Ghost CMS API from R

问题

我正在尝试使用内置的 Admin API 从 R 连接到本地的 Ghost CMS 实例。有一份很好的文档 (https://ghost.org/docs/admin-api/#token-authentication),介绍了如何在各种编程语言中进行连接,但不幸的是没有提供 R 的说明。我已经编写了以下代码,但在尝试创建测试文章时不幸收到了 401 错误。非常感谢任何帮助。

R 代码:

  1. api_admin_key <-
  2. "xxxxxx:yyyyyyyyyyyyyyy"
  3. api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
  4. names(api_admin_key) <- c("id", "secret")
  5. # 准备头部和负载
  6. iat <- as.integer(Sys.time())
  7. header <-
  8. list(alg = 'HS256', typ = 'JWT', kid = api_admin_key[["id"]])
  9. # 创建令牌(包括解码密钥)
  10. payload <-
  11. jose::jwt_claim(iat = iat,
  12. exp = iat + 5 * 60,
  13. aud = '/admin/')
  14. token <-
  15. jose::jwt_encode_hmac(
  16. claim = payload,
  17. secret = charToRaw(api_admin_key[["secret"]]),
  18. size = 256,
  19. header = header
  20. )
  21. # 发送经过身份验证的请求以创建文章
  22. url <- 'http://localhost:2368/ghost/api/admin/posts/'
  23. headers <- c('Authorization' = paste("Ghost", token))
  24. body <- list(posts = list(
  25. "title" = 'Hello World',
  26. "html" = "<p>My post content. Work in progress...</p>",
  27. "status" = "published"
  28. )
  29. )
  30. httr::POST(url,
  31. body = body,
  32. encode = "json",
  33. httr::add_headers(.headers = headers))
  1. <details>
  2. <summary>英文:</summary>
  3. 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.
  4. __R__ code:
  5. api_admin_key &lt;-
  6. &quot;xxxxxx:yyyyyyyyyyyyyyy&quot;
  7. api_admin_key &lt;- unlist(strsplit(x = api_admin_key, split = &quot;:&quot;))
  8. names(api_admin_key) &lt;- c(&quot;id&quot;, &quot;secret&quot;)
  9. # Prepare header and payload
  10. iat &lt;- as.integer(Sys.time())
  11. header &lt;-
  12. list(alg = &#39;HS256&#39;, typ = &#39;JWT&#39;, kid = api_admin_key[[&quot;id&quot;]])
  13. # Create the token (including decoding secret)
  14. payload &lt;-
  15. jose::jwt_claim(iat = iat,
  16. exp = iat + 5 * 60,
  17. aud = &#39;/admin/&#39;)
  18. token &lt;-
  19. jose::jwt_encode_hmac(
  20. claim = payload,
  21. secret = charToRaw(api_admin_key[[&quot;secret&quot;]]),
  22. size = 256,
  23. header = header
  24. )
  25. # Make an authenticated request to create a post
  26. url &lt;- &#39;http://localhost:2368/ghost/api/admin/posts/&#39;
  27. headers &lt;- c(&#39;Authorization&#39; = paste(&quot;Ghost&quot;, token))
  28. body &lt;- list(posts = list(
  29. &quot;title&quot; = &#39;Hello World&#39;,
  30. &quot;html&quot; = &quot;&lt;p&gt;My post content. Work in progress...&lt;/p&gt;&quot;,
  31. &quot;status&quot; = &quot;published&quot;
  32. )
  33. )
  34. httr::POST(url,
  35. body = body,
  36. encode = &quot;json&quot;,
  37. httr::add_headers(.headers = headers))
  38. [1]: https://ghost.org/docs/admin-api/#token-authentication
  39. </details>
  40. # 答案1
  41. **得分**: 2
  42. 看起来问题出在你传递给 `jwt_encode_hmac()` 的 `secret=` 参数上。`charToRaw` 函数不能理解十六进制数字。它只使用ASCII字符代码。要进行转换,你需要使用来自[这个现有问题](https://stackoverflow.com/questions/70884796/convert-hexadecimal-string-to-bytes-in-r)的其中一个 `hex_to_raw` 函数。我将在这里使用一个:
  43. ```R
  44. hex_to_raw <- function(x) {
  45. digits <- strtoi(strsplit(x, "")[[1]], base=16L)
  46. as.raw(bitwShiftL(digits[c(TRUE, FALSE)],4) + digits[c(FALSE, TRUE)])
  47. }

此外,你不需要在头部指定 alg 和 typ,因为这些信息将由函数自动添加。所以你可以使用以下方式构建你的令牌:

  1. api_admin_key <- "adam:12bd18f2cd12"
  2. api_admin_key <- unlist(strsplit(x = api_admin_key, split = ":"))
  3. names(api_admin_key) <- c("id", "secret")
  4. # 准备头部和负载
  5. iat <- as.integer(Sys.time())
  6. header <- list(kid = api_admin_key[["id"]])
  7. # 创建令牌(包括解码密钥)
  8. payload <-
  9. jose::jwt_claim(iat = iat,
  10. exp = iat + 5 * 60,
  11. aud = '/admin/')
  12. token <-
  13. jose::jwt_encode_hmac(
  14. claim = payload,
  15. secret = hex_to_raw(api_admin_key[["secret"]]),
  16. size = 256,
  17. header = header
  18. )

我使用了 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

  1. hex_to_raw &lt;- function(x) {
  2. digits &lt;- strtoi(strsplit(x, &quot;&quot;)[[1]], base=16L)
  3. as.raw(bitwShiftL(digits[c(TRUE, FALSE)],4) + digits[c(FALSE, TRUE)])
  4. }

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

  1. api_admin_key &lt;- &quot;adam:12bd18f2cd12&quot;
  2. api_admin_key &lt;- unlist(strsplit(x = api_admin_key, split = &quot;:&quot;))
  3. names(api_admin_key) &lt;- c(&quot;id&quot;, &quot;secret&quot;)
  4. # Prepare header and payload
  5. iat &lt;- as.integer(Sys.time())
  6. header &lt;- list(kid = api_admin_key[[&quot;id&quot;]])
  7. # Create the token (including decoding secret)
  8. payload &lt;-
  9. jose::jwt_claim(iat = iat,
  10. exp = iat + 5 * 60,
  11. aud = &#39;/admin/&#39;)
  12. token &lt;-
  13. jose::jwt_encode_hmac(
  14. claim = payload,
  15. secret = hex_to_raw(api_admin_key[[&quot;secret&quot;]]),
  16. size = 256,
  17. header = header
  18. )

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"

huangapple
  • 本文由 发表于 2023年8月4日 03:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定