StackMode, an Emacs client for StackExchange正在快速取得进展,现在我们需要能够对API进行authenticated requests以继续测试。 (300请求限制开始限制我一天可以做多少测试。)
免责声明:我知道非常关于网络开发;这是我正在专业领域的一个领域。如果我滥用任何条款,请随时在评论中纠正我,请原谅。谢谢!
StackExchange API使用OAuth 2.0身份验证。由于这是具有客户端授权的本地客户端应用程序。我有StackExchange提供给我的以下信息:
提供以下额外信息:
为了保持一般和明确的任何答案,您可以使用my-client-id
(等)来表示值。我认为我可以分享的实际值是available on 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请求的唯一事情(从上面)显然是
如何在Elisp中实现此流程?
oauth2-auth-and-store
并设置适当的变量。打开
打开
使用此网址
已成功添加应用
但我没有提供oauth2
除了答案之外,当然也欢迎PR。
答案 0 :(得分:3)
这是一个简单的例子。简而言之,这将在客户端浏览器中打开auth url,要求用户允许该应用,然后重定向到docs(隐式身份验证)中所述的/oauth/login_success
网址。
此代码提示用户粘贴login_success
URL完成,然后解析并保存access_token
,然后可以将其用于后续调用api。定义了两个交互式函数:so-authenticate
执行上述身份验证步骤,so-read-inbox
获取经过身份验证的用户收件箱的api数据并将其转储到消息缓冲区。
警告,此示例没有错误处理!
至少,您需要添加对身份验证失败,API请求失败和令牌过期的检查。您可以在致电so-read-inbox
之前尝试致电so-authenticate
来查看示例api错误。
要运行,请将以下内容粘贴到缓冲区中,然后设置so--client-id
和so--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)))
现在很有趣解析响应! :)
答案 1 :(得分:2)
我会尽可能多地回答这个问题。我对Lisp一无所知,但我对Stack Exchange API和授权流程非常熟悉。
“300请求限制开始限制我一天可以做多少测试。”
您可以将API密钥附加到方法网址(&key=...
)的查询字符串中,将此限制升级为10,000个查询/天。
“实际值 - 我认为我可以分享的那些,可以在GitHub上找到。”
是的,您可以安全地分享这些内容,因为任何带有这些值的应用程序都可以轻松地进行逆向工程或反编译以提取值。
“4。使用此URL”
打开[...]页面[...]
这是预期的行为。在屏幕截图中,授权成功,URL的哈希包含访问令牌。您需要此令牌才能访问某些方法,例如/inbox
。
您可能想要做的事情看起来像这样:
access_token
和key
(API密钥)参数。