混合环的 `wrap-defaults`' 和 lib-noir 的 `wrap-noir-session` 时出现奇怪的 session 管理错误
Weird session management bug when mixing ring's `wrap-defaults`' and lib-noir's `wrap-noir-session`
我有一个使用 noir.session
的 ring
网络应用程序,如下所示:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults site-defaults))) ; both from ring.middleware.defaults
但是,似乎 session 变量在请求之间丢失了。服务器不断发送 Set-Cookie
header 即使客户端提供了 Cookie
header.
通过反复试验,我发现当我如下禁用环的 anti-forgery 包装器时,相同的 session 存在于请求中:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))))
但我当然不想要那样。为什么会这样,如何在不冒 CSRF 攻击风险的情况下解决我的问题?
浏览所有涉及的中间件的源代码,我发现 lib-noir 的 wrap-noir-session
重新实现了 ring 的 wrap-session
的部分内容。这让我进行了以下实验:
(def app (-> app-routes
(session/wrap-noir-session {:store (memory-store)})
(wrap-defaults (assoc site-defaults :session false))))
在这里,会话也跨请求存在。
罪魁祸首:wrap-defaults
已经应用了 wrap-session
,因此当 wrap-noir-session
处理程序也被列出时,wrap-session
实际上被调用了两次。
最终的解决方案再简单不过了:改用wrap-noir-session*
。根据文档,它"expects that wrap-session has already been used." 好像wrap-noir-session
.
正好相反
(def app (-> app-routes
(session/wrap-noir-session*)
(wrap-defaults site-defaults)))
希望这能为您节省一些时间。
我有一个使用 noir.session
的 ring
网络应用程序,如下所示:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults site-defaults))) ; both from ring.middleware.defaults
但是,似乎 session 变量在请求之间丢失了。服务器不断发送 Set-Cookie
header 即使客户端提供了 Cookie
header.
通过反复试验,我发现当我如下禁用环的 anti-forgery 包装器时,相同的 session 存在于请求中:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))))
但我当然不想要那样。为什么会这样,如何在不冒 CSRF 攻击风险的情况下解决我的问题?
浏览所有涉及的中间件的源代码,我发现 lib-noir 的 wrap-noir-session
重新实现了 ring 的 wrap-session
的部分内容。这让我进行了以下实验:
(def app (-> app-routes
(session/wrap-noir-session {:store (memory-store)})
(wrap-defaults (assoc site-defaults :session false))))
在这里,会话也跨请求存在。
罪魁祸首:wrap-defaults
已经应用了 wrap-session
,因此当 wrap-noir-session
处理程序也被列出时,wrap-session
实际上被调用了两次。
最终的解决方案再简单不过了:改用wrap-noir-session*
。根据文档,它"expects that wrap-session has already been used." 好像wrap-noir-session
.
(def app (-> app-routes
(session/wrap-noir-session*)
(wrap-defaults site-defaults)))
希望这能为您节省一些时间。