【发布时间】:2013-12-14 21:47:57
【问题描述】:
我正在尝试将 Friend 身份验证和授权集成到 Clojure/Compojure 单页 Web 应用程序中。
我有一个由 Angular 控制器支持的登录表单,并且该控制器使用 AJAX 对 Web 应用程序的用户名和密码进行身份验证,并获取经过身份验证的用户记录。因此,我不想要 Friend 基于表单的登录提供的默认行为 - 我基本上想要依赖 HTTP 状态代码,并且我确实不想要任何 Friend 页面重定向。
例如,发出未经身份验证的请求应仅返回 401 状态代码,并且不应重定向到“/login”。我通过在配置 Friend 时指定自定义“:unauthenticated-handler”来完成这部分工作(代码包含在下面)。
在成功登录时,我只需要 200 状态代码,而不是重定向到最初请求的页面。这是我无法工作的。
我根据各种示例编写了一个自定义好友身份验证工作流程(我的 Clojure 技能目前处于初级水平):
(defn my-auth
[& {:keys [credential-fn]}]
(routes
(GET "/logout" req
(friend/logout* {:status 200}))
(POST "/login" {{:keys [username password]} :params}
(if-let [user-record (-> username credential-fn)]
(if
(and
[user-record password]
(creds/bcrypt-verify password (:password user-record)))
(let [user-record (dissoc user-record :password)]
(workflows/make-auth user-record {:cemerick.friend/workflow :my-auth :cemerick.friend/redirect-on-auth? true}))
{:status 401})
{:status 401}))))
这是我声明了中间件的处理程序:
(def app
(->
(handler/site
(friend/authenticate app-routes
{:credential-fn (partial creds/bcrypt-credential-fn my-credential-fn)
:unauthenticated-handler unauthenticated
:workflows [(my-auth :credential-fn my-credential-fn)]}))
(session/wrap-session)
(params/wrap-keyword-params)
(json/wrap-json-body)
(json/wrap-json-response {:pretty true})))
以及上面引用的附加处理函数:
(defn unauthenticated [v]
{:status 401 :body "Unauthenticated"})
最后是一个额外的路由片段来测试身份验证:
(GET "/auth" req
(friend/authenticated (str "You have successfully authenticated as "
(friend/current-authentication))))
这大部分有效,几乎可以满足我的所有需求。
因为“redirect-on-auth?”在“make-auth”中为真,成功登录时会生成一个页面重定向 - 我想阻止该重定向,所以我将值设置为 false。但是,这个单一的更改会导致 404 和登录失败。
除了 Friend 身份验证映射之外,我还需要以某种方式在此处返回 200 状态代码,并且我还想在响应正文中返回“用户记录”,以便客户端应用程序可以根据用户定制 UI角色(我已经将 JSON 请求/响应打包并工作)。
所以我认为当我调用 Friend“make-auth”函数时我需要与此等效的功能:
{:status 200 :body user-record}
但是,我似乎可以拥有身份验证映射或响应 - 但不能同时拥有。
这可以通过 Friend 实现吗?如果可以,如何实现?
【问题讨论】:
-
可能与此有关:github.com/cemerick/friend/issues/83,暗示目前不可能,需要向 Friend 修复。
-
是的,似乎是这样。
标签: authentication clojure compojure