Skip to content
zengxinhui edited this page Feb 11, 2018 · 3 revisions

在Ring中,会话(Sessions)的工作方式可能跟你预计的有一点不同,因为Ring试图尽可能的变得函数式化.

会话数据通过请求map中的:sessionkey被传递.下面的例子打印出会话中的当前的用户名.

(use 'ring.middleware.session
     'ring.util.response)

(defn handler [{session :session}]
  (response (str "Hello " (:username session))))

(def app
  (wrap-session handler))

为了改变会话数据,你可以添加一个包含更新过后的会话数据的:sessionkey到一个响应中.下一个例子统计了当前会话访问页面的次数.

(defn handler [{session :session}]
  (let [count   (:count session 0)
        session (assoc session :count (inc count))]
    (-> (response (str "You accessed this page " count " times."))
        (assoc :session session))))

为了完全删除session,在响应中设置:sessionkey为nil:

(defn handler [request]
  (-> (response "Session deleted.")
      (assoc :session nil)))

如果你想简单的重新创建会话,由于特权提升,添加:recreatekey到会话元数据(metadata)中.这将会导致会话标识符被发送到浏览器,由此去改变.

(defn handler [request]
  (-> (response "Session identifier recreated")
      (assoc :session (vary-meta (:session request) assoc :recreate true))))

经常性的你想要控制会话cookie在用户的浏览器上存在多长时间.你可以使用:cookie-attrs选项去改变会话cookie的属性:

(def app
  (wrap-session handler {:cookie-attrs {:max-age 3600}}))

在这个例子中,cookie的最大生命周期被设置成3600秒,或者1小时.

你也可以使用这个选项确保站点的会话cookie通过HTTPS被保护而不是通过HTTP被泄露:

(def app
  (wrap-session handler {:cookie-attrs {:secure true}}))

会话存储

会话数据被存储在会话储存中,Ring里面有两个储存方式:

  • ring.middleware.session.memory/memory-store - 在内存中储存会话
  • ring.middleware.session.cookie/cookie-store - 储存加密的会话到一个cookie上

默认情况下,Ring存储会话数据在内存中,但是这可以被:store选项重写:

(use 'ring.middleware.session.cookie)

(def app
  (wrap-session handler {:store (cookie-store {:key "a 16-byte secret"})})

通过实现ring.middleware.session.store/SessionStore protocol,你可以编写自己的会话储存方式:

(use 'ring.middleware.session.store)

(deftype CustomStore []
  SessionStore
  (read-session [_ key]
    (read-data key))
  (write-session [_ key data]
    (let [key (or key (generate-new-random-key))]
      (save-data key data)
      key))
  (delete-session [_ key]
    (delete-data key)
    nil))

注意当你编写会话,如果这是一个新的会话,key将会是nil的.会话储存方式应该预计是这样的,而且会生成一个随机key.这是十分重要的,这个key不会被猜解出,否则恶意的用户能够访问其他用户的会话数据.