我正在尝试将Friend身份验证和授权集成到Clojure / Compojure单页Web应用程序中.
我有一个由Angular控制器支持的登录表单,该控制器使用AJAX对Web应用程序验证用户名和密码,并获取经过身份验证的用户记录.因此,我不希望Friend基于表单的登录提供默认行为 – 我基本上想要依赖HTTP状态代码,我不想要任何朋友页面重定向.
例如,进行未经身份验证的请求应该只返回401状态代码,而不应重定向到“/ login”.通过在配置好友时指定自定义“: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(I已经有JSON请求/响应包装和工作).
因此,当我调用Friend“make-auth”函数时,我认为我需要等效于此:
{:status 200 :body user-record}
然而,似乎我可以拥有身份验证映射或响应 – 但不能同时使用.
这可以通过朋友实现,如果是这样的话怎么样?
解决方法
您需要:redirect-on-auth?如果为false,您需要将响应包装在响应映射中{:status 200:body(workflows / make-auth …)}.请注意,您可能需要将主体序列化为String或其他可以处理的内容.