9

我得到会话,来自我曾经使用过的 PHP

<?php
session_start();
$_SESSION["key"] = "val";
echo $_SESSION["key"];
?>

在服务器端设置一个或多个键及其值,并能够检索或覆盖它,直到会话到期。

与大猩猩/会话相同

var(
    sessionStore  *sessions.CookieStore
    sessionSecret []byte = make([]byte, 64)
    session       *sessions.Session
)

func init(){
    sessionSecret = []byte("12345678901234567890123456789012")
    sessionStore = sessions.NewCookieStore(sessionSecret)
    session = sessions.NewSession(sessionStore, "session_name")
}

func SetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, "session_name")
    session.Values["key"] = "val"
    session.Save(r, w)
}

func GetSessionHandler(w http.ResponseWriter, r *http.Request) {
    session, _ = sessionStore.Get(r, "session_name")
    fmt.FPrintln(session.Values["key"])
}

现在我不明白大猩猩/上下文的意义是什么。我知道上下文是什么,但是...我不知道它如何适应大局。它说它绑定到当前请求。stackoverflow 上的另一个问题是在编写 Per-Handler Middleware的上下文中“仅使用 gorilla/context 就足够了” 。

但如果它是请求绑定... err.. 语法错误,则不计算。如果鸭子漂浮在水面上,那么女巫是用木头制成的。而且因为鸭子也能浮在水面上,如果她的体重和鸭子一样,她一定是个女巫。或类似的东西 ;)

当它是请求绑定的时候,它作为一个中间件“管理器”怎么能有用,我不能在全局范围内设置它。您能否举例说明如何将 gorilla/sessions 与 gorilla/context 一起使用?

4

2 回答 2

9

作为提出另一个问题的人:

  • gorilla/context 允许您在请求中存储数据。如果您有一些中间件在决定继续之前对请求进行了一些预处理(即反 CSRF),您可能希望在请求中存储一个令牌,以便您的处理程序可以将其传递给模板。gorilla/context 文档很好地解释了它:

...路由器可以设置从 URL 中提取的变量,然后应用程序处理程序可以访问这些值,或者它可以用于存储要在请求结束时保存的会话值。还有其他几种常见用途。

  • 您可能希望在会话中存储数据:来自表单提交的错误消息、用户 ID 或该访问者的 CSRF 令牌的“规范”版本可能会存储在这里。如果您尝试在请求上下文中存储错误消息,然后重定向用户,您将丢失它(这是一个新请求)。

那么为什么要在会话上使用上下文呢?它更轻巧,并允许您将应用程序的各个部分(通常是 HTTP 中间件!)彼此分离。

例子:

  1. 请求进来
  2. CSRF 中间件检查会话中是否存在现有的 CSRF 令牌。不存在,所以设置一个。
  3. 它还将这个新令牌(通过请求上下文!)传递给呈现您的表单的处理程序,因此它可以在模板中呈现它(否则您将不得不再次从会话中提取令牌,这是浪费精力)
  4. 请求完成。
  5. 提交表单的新请求
  6. 令牌仍然存在于会话中,因此我们可以将其与表单中提交的令牌进行比较。
  7. 如果它签出,我们将继续处理表格
  8. 如果没有,我们可以在会话中保存一个错误(一条闪存消息;即在读取后被擦除的消息)并重新定向。
  9. 此重定向是一个新请求,因此我们无法通过此处的请求上下文传递错误消息。
于 2013-12-06T03:30:04.520 回答
0

一个例子。

我正在编写这个多社区论坛软件。现在我有一个 gorilla/mux 路由器,它为主域提供不同的内容,另一个路由器提供由 subdomain.domain.tld 过滤的不同内容。

上下文在这里非常有用,否则你会一遍又一遍地重复自己。因此,如果我知道对于子域路由器,每个请求都会执行字符串操作以找出子域名并检查它是否存在于数据库中,我可以在这里(在上下文中)为每个请求执行此操作,然后将子域名存储在上下文变量。同样,如果设置了论坛的类别 slug 或论坛 slug 或线程 slug 将其传递给处理程序,请将需要在“上下文”中完成的处理保持在处理程序中并减少代码。

所以上下文的优势本质上是保持代码干燥。

就像 elihrar 所写的那样,他的 CSRF 令牌示例。如果您知道需要在每个请求上检查 CSRF 令牌 - 不要在每个需要执行此操作的处理程序中重复此检查,而是编写一个上下文包装器 (/http.Handler) 并为每个请求执行此操作。

于 2014-02-17T16:45:52.497 回答