Authentication 在Clojure Web应用程序中使用JSON请求体而不是请求参数进行朋友身份验证

Authentication 在Clojure Web应用程序中使用JSON请求体而不是请求参数进行朋友身份验证,authentication,clojure,compojure,Authentication,Clojure,Compojure,我正在使用Friend将身份验证构建到Compojure web应用程序中 我已经为朋友定义了一个定制的身份验证工作流: (defn authentication-workflow [] (routes (GET "/logout" req (friend/logout* {:status 200})) (POST "/login" {{:keys [username password]} :params} (if-let [user-record (

我正在使用Friend将身份验证构建到Compojure web应用程序中

我已经为朋友定义了一个定制的身份验证工作流:

(defn authentication-workflow []
  (routes
    (GET "/logout" req
      (friend/logout* {:status 200}))
    (POST "/login" {{:keys [username password]} :params}
      (if-let [user-record (authenticate-user username password)]
        (workflows/make-auth user-record {:cemerick.friend/workflow :authorisation-workflow})
        {:status 401}))))
身份验证部分已考虑在内:

(defn authenticate-user [username password]
  (if-let [user-record (get-user-for-username username)]
    (if (creds/bcrypt-verify password (:password user-record))
      (dissoc user-record :password))))
这是可行的,但是

我正在使用AngularJS,并且必须发布请求参数,这会导致一些丑陋的角度代码(抄袭StackOverflow答案的其他地方):

我更愿意执行这个简单得多的调用,通过请求体发布一个JSON对象:

$http.post('/login', {username: username, password: password})
(defn authentication-workflow []
  (routes
    (GET "/logout" req
      (friend/logout* {:status 200}))
    (POST "/login" {body :body}
      (if-let [user-record (authenticate-user body)]
        (workflows/make-auth user-record {:cemerick.friend/workflow :authorisation-workflow})
        {:status 401}))))
我试图在身份验证处理程序中使用“:body”而不是“:params”,但是:body的值在我看来既不是JSON也不是Clojure,所以我不知道如何使用它:

{username me@myapp.com, password password}
我已经让JSON请求/响应映射工作流为我的RESTAPI处理程序正常工作,并且我已经检查了JSON的请求头(例如ContentType)是否正确


那么,使用Compojure/Friend可以做到这一点吗?如果可以,如何做到呢?

我怀疑您的包装程序的应用顺序是错误的。检查
ring.middleware.json/wrap json body
是否在友元包装器之前(外部)应用

e、 g


否则,一个快速修复方法可能是将整个应用程序包装到
ring.middleware.json/wrap json params

以下是一些工作代码和说明

首先是朋友工作流,使用请求正文:

$http.post('/login', {username: username, password: password})
(defn authentication-workflow []
  (routes
    (GET "/logout" req
      (friend/logout* {:status 200}))
    (POST "/login" {body :body}
      (if-let [user-record (authenticate-user body)]
        (workflows/make-auth user-record {:cemerick.friend/workflow :authorisation-workflow})
        {:status 401}))))
第二,身份验证功能:

(defn authenticate-user [{username "username" password "password"}]
  (if-let [user-record (get-user-for-username username)]
    (if (creds/bcrypt-verify password (:password user-record))
      (dissoc user-record :password))))
第三,使用中间件的Compojure应用程序声明:

(def app
  (-> (handler/site
        (friend/authenticate app-routes
          {:workflows [(authentication-workflow)]}))
      (params/wrap-keyword-params)
      (json/wrap-json-body)
      (json/wrap-json-response {:pretty true})))
最后,发布凭证的AngularJS代码片段(用户名和密码来自AngularJS模型):

所以发生的事情是

javascript代码将JSON发布到web应用程序登录URL。“Content Type”头自动设置为“application/json”,请求主体自动编码为json,例如:

{"username":"batman@batcave.org","password":"tumblerrocks"}
在服务器上,中间件将JSON解析为Clojure映射,并通过“:body”关键字将其呈现给处理程序:

然后将请求路由到自定义好友身份验证工作流

最后,从Clojure映射中提取提交的值并用于对用户进行身份验证

{"username":"batman@batcave.org","password":"tumblerrocks"}
{username batman@batcave.org, password tumblerrocks}