10

StackMode正在迅速取得进展, StackMode 是StackExchange 的 Emacs 客户端,现在我们需要能够向 API 发出经过身份验证的请求以继续测试。(300 个请求的限制开始限制我一天可以进行多少测试。)

免责声明:我对 Web 开发知之甚少这是我专业从事的领域之一。如果我滥用任何术语,请原谅我,并随时在评论中纠正我。谢谢!

StackExchange API 使用 OAuth 2.0 身份验证。由于这是具有客户端授权的本地客户端应用程序。StackExchange 向我提供了以下信息:

  • 客户编号
  • 客户端密钥(不得共享,因此在此流程中不需要)
  • 钥匙
  • 说明(与 OAuth 无关)
  • OAuth 域
  • 申请网站(与 OAuth 无关)
  • 应用程序图标(与 OAuth 无关)
  • Stack Apps Post(与 OAuth 无关)

带有以下额外信息:

  • 客户端流已启用
  • 桌面 OAuth 重定向 Uri 已启用

为了使任何答案既通用又明确,您可以使用my-client-id(等)作为值。实际值——我认为我可以分享的值,可以在 GitHub 上找到


我已经研究了半天,但与开始时相比,我离解决方案的距离并不远。我得到的最接近的是这段代码:

(require 'oauth2) ; available via GNU ELPA
(defconst stack-auth-token
  (make-oauth2-token
   :client-id stack-auth--client-id
   :client-secret stack-auth--key))

;; this doesn't use the above, but it does open an auth page on SE
(oauth2-auth-and-store
 "https://stackexchange.com/oauth/dialog"
 nil nil
 stack-auth--client-id
 stack-auth--key
 "https://stackexchange.com/oauth/login_success")

我必须提供 OAuth2 请求(从上面)的唯一事情显然是

  • 客户编号
  • 钥匙
  • OAuth 域

如何在 Elisp 中实现这个流程?


当前的“流量”

  1. oauth2-auth-and-store使用适当的变量集执行。
  2. 打开

    授权

  3. 点击“批准”
  4. 打开

    页

    用这个网址

    网址

  5. 应用添加成功

    添加

  6. 但我没有代码可提供oauth2

    迅速的

除了答案,当然也欢迎 PR。

4

2 回答 2

3

这是一个简单的例子。简而言之,这将在客户端浏览器中打开 auth url,要求用户允许应用程序,然后按照文档/oauth/login_success中的描述重定向到 url (隐式身份验证)。

此代码提示用户login_success完整粘贴 URL,然后解析并保存该 URL,access_token然后可用于对 api 的后续调用。定义了两个交互函数:so-authenticate执行上述验证步骤so-read-inbox,获取已验证用户收件箱的 api 数据并将其转储到消息缓冲区。


警告,这个例子没有错误处理!

至少您需要添加对身份验证失败、api 请求失败和令牌过期的检查。so-read-inbox您可以通过在调用之前尝试调用来查看示例 api 错误so-authenticate


要运行,请将以下内容粘贴到缓冲区中,然后设置so--client-idso--client-key变量M-x eval-buffer

然后,您可以使用M-x so-authenticate来进行身份验证并M-x so-read-inbox转储收件箱响应。

(require 'json)

(defvar so--client-id "")  ; SET THIS
(defvar so--client-key "") ; AND THIS

(defvar so--auth-url "https://stackexchange.com/oauth/dialog?")
(defvar so--redirect-url "https://stackexchange.com/oauth/login_success")
(defvar so--api-inbox-url "https://api.stackexchange.com/inbox?")

(defvar so--current-token nil) ; this will get set after authentication

(defun so-authenticate ()
  (interactive)
  (so--open-auth))

(defun so-read-inbox()
  (interactive)
  (so--retrieve-inbox))

;; Open auth url in browser and call so--get-save-token.
(defun so--open-auth ()
  (let ((auth-url
     (concat so--auth-url (url-build-query-string
               `((client_id ,so--client-id)
                 (scope "read_inbox")
                 (redirect_uri ,so--redirect-url))))))
(browse-url auth-url))
  (so--get-save-token))

;; Prompt user for callback URL, extract token and save in so--current-token
(defun so--get-save-token ()
  (let* ((post-auth-url-string (read-string "Enter URL from your browser: "))
     (token (nth 2 (split-string post-auth-url-string "[[#=&]"))))
(setq so--current-token token)
(message "Saved token: %S" token)))

;; Make a request for our inbox data
(defun so--retrieve-inbox()
  (let ((inbox-url (concat so--api-inbox-url
               (url-build-query-string
            `((access_token ,so--current-token) ; the token from auth
              (key ,so--client-key))))))        ; your client key
(url-retrieve inbox-url 'so--retrieve-inbox-cb)))

;; Parse json response for inbox request.
;; This simply dumps the parsed data to your messages buffer.
(defun so--retrieve-inbox-cb (status)
  (goto-char (point-min))
  (re-search-forward "^$")
  (let ((inbox-data (json-read)))
(message "inbox data: %S" inbox-data)))

现在享受解析响应的乐趣吧!:)

于 2014-11-05T22:19:01.027 回答
2

我会尽量回答这个问题。我对 Lisp 一无所知,但我对 Stack Exchange API 和授权流程非常熟悉。

“300 个请求的限制开始限制我一天可以进行多少测试。”

您可以通过将 API 密钥附加到方法 URL ( &key=...) 的查询字符串,将此限制升级为每天 10,000 次查询。

“实际价值——我认为我可以分享的那些,可以在 GitHub 上找到。”

是的,您可以安全地分享这些值,因为任何带有这些值的应用程序都可以很容易地被逆向工程或反编译以提取这些值。

“4. 使用此 URL 打开 [...] 页面 [...]”

这是预期的行为。在您的屏幕截图中,授权成功并且 URL 的哈希包含访问令牌。您将需要此令牌来访问某些方法,例如/inbox.

你可能想要做的看起来像这样:

  1. 继续您一直在做的事情,直到您的示例中的第 4 步结束。
  2. 在 Emacs 中提示用户输入当前显示的 URL。他们将按原样复制和粘贴。
  3. 提取哈希(最右边的“#”之后的所有内容)并像解析查询字符串一样解析它。access_token 参数包含您需要的值。
  4. 调用受保护方法时使用access_tokenand (API 密钥)参数。key
于 2014-11-05T04:18:38.597 回答