按正确顺序放置 Clojure Ring 中间件
我的 Clojure 服务器中间件遇到问题。我的应用程序有以下要求:
某些路线应该可以毫无问题地访问。其他人需要基本身份验证,因此我希望有一个位于所有处理程序函数前面的身份验证函数,并确保请求得到验证。我一直在为此使用 Ring-basic-authentication 处理程序,尤其是 how 的说明将您的公共和私人路线分开。
但是,我还希望在
Authorization:
标头中发送的参数在路由控制器中可用。为此,我一直在compojure.handler
中使用 Compojure 的site
函数,它将变量放入请求的:params
字典中(请参阅示例 Compojure POST 中缺少表单参数request)
但是我似乎无法让 401 授权和参数同时工作。如果我尝试这样做:
; this is a stripped down sample case:
(defn authenticated?
"authenticate the request"
[service-name token]
(:valid (model/valid-service-and-token service-name token)))
(defroutes token-routes
(POST "/api/:service-name/phone" request (add-phone request)))
(defroutes public-routes
controller/routes
; match anything in the static dir at resources/public
(route/resources "/"))
(defroutes authviasms-handler
public-routes
(auth/wrap-basic-authentication
controller/token-routes authenticated?))
;handler is compojure.handler
(def application (handler/site authviasms-handler))
(defn start [port]
(ring/run-jetty (var application) {:port (or port 8000) :join? false}))
授权变量可以在 authenticated?
函数中访问,但不能在路由中访问。
显然,这不是一个非常普遍的例子,但我觉得我真的在旋转我的轮子,只是随机更改中间件顺序并希望一切正常。我希望为我的具体示例提供一些帮助,并了解有关如何包装中间件以使事情正确执行的更多信息。
谢谢, 凯文
I'm having trouble with my Clojure server middlewares. My app has the following requirements:
Some routes should be accessible with no problems. Others require basic authentication, so I'd like to have an authentication function that sits in front of all the handler functions and makes sure the request is verified. I've been using the ring-basic-authentication handler for this, especially the instructions on how to separate your public and private routes.
However, I'd also like the params sent in the
Authorization:
header to be available in the route controller. For this I've been using Compojure'ssite
function incompojure.handler
, which puts variables in the:params
dictionary of the request (see for example Missing form parameters in Compojure POST request)
However I can't seem to get both 401 authorization and the parameters to work at the same time. If I try this:
; this is a stripped down sample case:
(defn authenticated?
"authenticate the request"
[service-name token]
(:valid (model/valid-service-and-token service-name token)))
(defroutes token-routes
(POST "/api/:service-name/phone" request (add-phone request)))
(defroutes public-routes
controller/routes
; match anything in the static dir at resources/public
(route/resources "/"))
(defroutes authviasms-handler
public-routes
(auth/wrap-basic-authentication
controller/token-routes authenticated?))
;handler is compojure.handler
(def application (handler/site authviasms-handler))
(defn start [port]
(ring/run-jetty (var application) {:port (or port 8000) :join? false}))
the authorization variables are accessible in the authenticated?
function, but not in the routes.
Obviously, this isn't a very general example, but I feel like I'm really spinning my wheels and just making changes at random to the middleware order and hoping things work. I'd appreciate some help both for my specific example, and learning more about how to wrap middlewares to make things execute correctly.
Thanks,
Kevin
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
AFAIK,ring.middleware.basic-authentication 不会从 request 中的 :params 读取任何内容,ring.core.request/site 也不会在其中放置任何与身份验证相关的内容。
但在任何环处理程序中,您仍然可以访问标头。类似于:
类似地,如果您确实愿意,您可以使用它来编写自己的中间件,将与身份验证相关的内容放入参数中。
AFAIK, ring.middleware.basic-authentication doesn't read anything from the :params in request and ring.core.request/site doesn't put anything authentication-related there either.
But in any ring handler, you can still access the headers. Something like:
Similarly, you can use that to write your own middleware to put authentication-related stuff in params, if you really want to.