如何在 Clojure 中使用 Goodreads 配置 OAuth

How to configure OAuth with Goodreads in Clojure

我正在尝试将 OAuth 配置为使用它来使用 Clojure 和 Compojure 框架从 Goodreads API 访问数据。我基本上想获得 Goodreads 成员拥有的好友列表。我应该提一下,我是 Clojure 的新手,也是 OAuth 的新手,并且通常是 API 身份验证的新手,所以如果能尽可能简单地解释它,我将不胜感激。

我试图在网上找到答案,但无法找到对我有帮助的答案,因为许多网站都处理特定的 OAuth API 配置,而且这些配置似乎与 API 和 API 在配置 OAuth 访问方面。此外,他们中没有多少人使用 Clojure 来解释 OAuth API 配置,而那些确实在特定 API 访问所需的方面差异太大的人。 Goodreads API 页面也不是很有帮助。最后我找到了 and tried to use it as a template to configure my OAuth access to the Goodreads API. It uses the clj-oauth 的答案,我试图将其与上述问题的答案结合使用,因为简单地用 Goodreads 地址替换该问题的答案中的数据是行不通的。这就是我现在所拥有的,但它只是 returns 一个 401 错误,我不知道我做错了什么:

(def okey "goodreads-key")

(def osecret "goodreads-secret")

(def consumer (oauth/make-consumer okey
                                   osecret
                                   "http://www.goodreads.com/oauth/request_token"
                                   "http://www.goodreads.com/oauth/access_token"
                                   "http://www.goodreads.com/oauth/authorize"
                                   :hmac-sha1))

(def request-token (oauth/request-token consumer nil))

(oauth/user-approval-uri consumer 
                         (:oauth_token request-token))

(def access-token-response (oauth/access-token consumer 
                                               request-token
                                               nil))

(defn test-get []
  (let [credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       "https://www.goodreads.com/friend/user/user-id-number?format=xml")]
    (http/get "https://www.goodreads.com/friend/user/user-id-number?format=xml" {:query-params credentials})))

clj-oauth 在客户端示例中说,请求令牌中应该有一个回调 uri,访问令牌响应中应该有一个验证器,但是由于我不熟悉 OAuth,所以我把 nil 放在那里.

上述问题的答案没有使用我代码中的以下几行:

(def request-token (oauth/request-token consumer nil))

(oauth/user-approval-uri consumer 
                         (:oauth_token request-token))

(def access-token-response (oauth/access-token consumer 
                                               request-token
                                               nil))

随后不使用“http://www.goodreads.com/oauth/request_token” “http://www.goodreads.com/oauth/access_tokenconsumer 中的“http://www.goodreads.com/oauth/authorize”地址也不使用 (:oauth_token access-token-response) (:oauth_token_secret access-token-response) 在 test-get 中,而是将这些值替换为 nil,但由于它不起作用,我尝试将它与上面提到的示例结合起来上面提到的clj-oauth github页面,还是不行。

我只是想从 Goodreads API 中获取成员朋友列表的 XML 响应,非常感谢任何帮助配置它。

所以我的 project.clj 看起来像这样:

:dependencies [[org.clojure/clojure "1.6.0"]
                 [clj-oauth "1.5.2"]
                 [clj-http "1.1.2"]]

示例代码:

(ns scratch.core
  (:require [oauth.client :as oauth]
            [clj-http.client :as http]))

(def consumer-key "your_key")
(def consumer-secret "your_secret")

;Step 1: Create an oath consumer object
(def consumer (oauth/make-consumer consumer-key
                                   consumer-secret
                                   "https://www.goodreads.com/oauth/request_token"
                                   "https://www.goodreads.com/oauth/access_token"
                                   "https://www.goodreads.com/oauth/authorize"
                                   :hmac-sha1))
;Step 2: Create a request token.  These can only be used once.  They usually expire as well.
(def request-token (oauth/request-token consumer nil))

;Step 3:  Have the goodreads user approve your application.  They can approve your application by visting the url
; produced by the call below.
(oauth/user-approval-uri consumer
                         (:oauth_token request-token))

;Step 4:  Once the goodreads user has approved your application, you can exchange the request token for an access token.
;An access token is per-user.  Goodreads in particular will only issue 1 per user, so don not lose this access token.
(def access-token-response (oauth/access-token consumer
                                               request-token
                                               nil))

;Step 5: Get the user id of the user who approved your application.
;you can parse the user id out from this.  I used clojure.zip, clojure.data.zip.xml, and clojure.data.xml to parse this out.
(defn get-user-id []
  (let [url "https://www.goodreads.com/api/auth_user"
        credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       url)]
    (http/get url {:query-params credentials})))

(get-user-id)

;Step 6: Get the friends of the user.
(defn get-friends [user-id]
  (let [url (str "https://www.goodreads.com/friend/user/" user-id)
        params {:format "xml"}
        credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       url
                                       params)]
    (http/get url {:query-params (merge credentials params)})))

(get-friends <a user id>)

编辑:

好的,我重新运行了上面的确切代码(编辑了 api 密钥和用户 ID)并且我 100% 确定它有效。我强烈建议创建一个一次性的 Goodreads 帐户来进行测试。

这是一个screenshot of a successful request