英文:
Go session variables?
问题
我对Go语言(Golang)还不熟悉,我正在编写一个基于Web的应用程序。我想使用会话变量,就像PHP中的那种变量(在一个页面到下一个页面可用,并且对于用户会话是唯一的)。Go语言中有类似的东西吗?如果没有,我该如何自己实现它们?或者还有其他替代方法吗?
英文:
I'm new to the Go language (Golang) and I'm writing a web-based application. I'd like to use session variables, like the kind in PHP (variables that are available from one page to the next and unique for a user session). Is there something like that in Go? If not, how would I go about implementing them myself? Or what alternatives methods are there?
答案1
得分: 17
除此之外,或许还有其他适用于Go的Web工具包,你可以自己开发。
可能的解决方案包括:
- 每个用户会话使用goroutine将会话变量存储在内存中。
- 将变量存储在会话cookie中。
- 使用数据库存储用户会话数据。
我将具体实现细节留给读者。
英文:
You probably want to take a look at gorilla. It has session support as documented here.
Other than that or possibly one of the other web toolkits for go you would have to roll your own.
Possible solutions might be:
- goroutine per user session to store session variables in memory.
- store your variables in a session cookie.
- use a database to store user session data.
I'll leave the implementation details of each of those to the reader.
答案2
得分: 6
这是一个备选方案,如果你只想要会话支持而不需要完整的网络工具包。
https://github.com/bpowers/seshcookie
英文:
Here's an alternative in case you just want session support without a complete web toolkit.
答案3
得分: 6
这是另一种选择(声明:我是作者):
https://github.com/icza/session
从文档中引用:
该软件包提供了一个易于使用、可扩展和安全的会话实现和管理。软件包文档可以在godoc.org上找到:
https://godoc.org/github.com/icza/session
这只是一个“仅仅”是HTTP会话实现和管理,您可以直接使用它,或者与任何现有的Go Web工具包和框架一起使用。
概述
该软件包有3个关键的“角色”:
Session
是(HTTP)会话接口。我们可以使用它来存储和检索常量和变量属性。Store
是一个会话存储接口,负责在服务器端存储会话并通过其ID检索它们。Manager
是一个会话管理器接口,负责从(传入的)HTTP请求中获取Session
,并将Session
添加到HTTP响应中,以让客户端了解会话。Manager
有一个后备的Store
,负责在服务器端管理Session
值。
该软件包的“角色”由接口表示,并为所有这些“角色”提供了各种实现。您不受提供的实现的限制,可以自由地为任何“角色”提供自己的实现。
用法
用法比这更简单。要获取与http.Request关联的当前会话:
sess := session.Get(r)
if sess == nil {
// 没有会话(尚未)
} else {
// 我们有一个会话,使用它
}
要创建一个新的会话(例如在成功登录时)并将其添加到http.ResponseWriter(以让客户端了解会话):
sess := session.NewSession()
session.Add(sess, w)
让我们看一个更高级的会话创建示例:让我们提供一个常量属性(在会话的生命周期内)和一个初始的可变属性:
sess := session.NewSessionOptions(&session.SessOptions{
CAttrs: map[string]interface{}{"UserName": userName},
Attrs: map[string]interface{}{"Count": 1},
})
要访问这些属性并更改"Count"
的值:
userName := sess.CAttr("UserName")
count := sess.Attr("Count").(int) // 类型断言,您可能想要检查它是否成功
sess.SetAttr("Count", count+1) // 增加计数
(当然,可变属性也可以在会话创建后使用Session.SetAttr()
添加,而不仅仅是在会话创建时。)
要删除会话(例如在注销时):
session.Remove(sess, w)
查看会话演示应用程序,其中展示了所有这些操作。
Google App Engine支持
该软件包提供了对Google App Engine(GAE)平台的支持。
文档中没有包含它(由于+build appengine
构建约束),但在这里:gae_memcache_store.go
该实现将会话存储在Memcache中,并将会话作为备份保存到Datastore中,以防数据从Memcache中删除。此行为是可选的,可以完全禁用Datastore。您还可以选择保存到Datastore是同步进行(在同一个goroutine中)还是异步进行(在另一个goroutine中),从而实现更快的响应时间。
我们可以使用NewMemcacheStore()
和NewMemcacheStoreOptions()
函数创建一个会话存储实现,该实现将会话存储在GAE的Memcache中。重要的是要注意,由于访问Memcache依赖于绑定到http.Request
的Appengine Context,因此返回的Store只能在请求的生命周期内使用!请注意,当Store关闭时,从中访问的会话将自动“刷新”,因此在请求结束时关闭Store非常重要;通常使用defer语句关闭传递给Store的会话管理器来完成这个操作。
因此,在每个请求处理中,我们必须使用新的Store创建一个新的会话管理器,并且我们可以使用会话管理器执行与会话相关的任务,类似于以下示例:
ctx := appengine.NewContext(r)
sessmgr := session.NewCookieManager(session.NewMemcacheStore(ctx))
defer sessmgr.Close() // 这将确保对会话所做的更改自动保存在Memcache中(以及可选的Datastore中)。
sess := sessmgr.Get(r) // 获取当前会话
if sess != nil {
// 会话存在,对其进行操作。
ctx.Infof("Count: %v", sess.Attr("Count"))
} else {
// 尚未有会话,让我们创建一个并添加它:
sess = session.NewSession()
sess.SetAttr("Count", 1)
sessmgr.Add(sess, w)
}
过期的会话不会自动从Datastore中删除。为了删除过期的会话,该软件包提供了一个PurgeExpiredSessFromDSFunc()
函数,该函数返回一个http.HandlerFunc
。建议将返回的处理程序函数注册到一个路径上,然后可以将其定义为定期调用的cron作业,例如每30分钟一次或其他时间间隔(根据您的选择)。由于cron处理程序可能运行长达10分钟,返回的处理程序将在8分钟时停止,以确保即使有更多过期但未删除的会话,也能安全地完成。可以像这样注册它:
http.HandleFunc("/demo/purge", session.PurgeExpiredSessFromDSFunc(""))
查看GAE会话演示应用程序,了解如何使用它。
演示的cron.yaml文件显示了如何定义cron作业以清除过期的会话。
查看GAE会话演示应用程序,了解如何在实际中使用它。
英文:
Here's another alternative (disclosure: I'm the author):
https://github.com/icza/session
Quoting from its doc:
This package provides an easy-to-use, extensible and secure session implementation and management. Package documentation can be found and godoc.org:
https://godoc.org/github.com/icza/session
This is "just" an HTTP session implementation and management, you can use it as-is, or with any existing Go web toolkits and frameworks.
Overview
There are 3 key players in the package:
Session
is the (HTTP) session interface. We can use it to store and retrieve constant and variable attributes from it.Store
is a session store interface which is responsible to store sessions and make them retrievable by their IDs at the server side.Manager
is a session manager interface which is responsible to acquire aSession
from an (incoming) HTTP request, and to add aSession
to an HTTP response to let the client know about the session. AManager
has a backingStore
which is responsible to manageSession
values at server side.
Players of this package are represented by interfaces, and various implementations are provided for all these players.
You are not bound by the provided implementations, feel free to provide your own implementations for any of the players.
Usage
Usage can't be simpler than this. To get the current session associated with the http.Request:
sess := session.Get(r)
if sess == nil {
// No session (yet)
} else {
// We have a session, use it
}
To create a new session (e.g. on a successful login) and add it to an http.ResponseWriter (to let the client know about the session):
sess := session.NewSession()
session.Add(sess, w)
Let's see a more advanced session creation: let's provide a constant attribute (for the lifetime of the session) and an initial, variable attribute:
sess := session.NewSessionOptions(&session.SessOptions{
CAttrs: map[string]interface{}{"UserName": userName},
Attrs: map[string]interface{}{"Count": 1},
})
And to access these attributes and change value of "Count"
:
userName := sess.CAttr("UserName")
count := sess.Attr("Count").(int) // Type assertion, you might wanna check if it succeeds
sess.SetAttr("Count", count+1) // Increment count
(Of course variable attributes can be added later on too with Session.SetAttr()
, not just at session creation.)
To remove a session (e.g. on logout):
session.Remove(sess, w)
Check out the session demo application which shows all these in action.
Google App Engine support
The package provides support for Google App Engine (GAE) platform.
The documentation doesn't include it (due to the +build appengine
build constraint), but here it is: gae_memcache_store.go
The implementation stores sessions in the Memcache and also saves sessions to the Datastore as a backup in case data would be removed from the Memcache. This behaviour is optional, Datastore can be disabled completely. You can also choose whether saving to Datastore happens synchronously (in the same goroutine) or asynchronously (in another goroutine), resulting in faster response times.
We can use NewMemcacheStore()
and NewMemcacheStoreOptions()
functions to create a session Store implementation which stores sessions in GAE's Memcache. Important to note that since accessing the Memcache relies on Appengine Context which is bound to an http.Request
, the returned Store can only be used for the lifetime of a request! Note that the Store will automatically "flush" sessions accessed from it when the Store is closed, so it is very important to close the Store at the end of your request; this is usually done by closing the session manager to which you passed the store (preferably with the defer statement).
So in each request handling we have to create a new session manager using a new Store, and we can use the session manager to do session-related tasks, something like this:
ctx := appengine.NewContext(r)
sessmgr := session.NewCookieManager(session.NewMemcacheStore(ctx))
defer sessmgr.Close() // This will ensure changes made to the session are auto-saved
// in Memcache (and optionally in the Datastore).
sess := sessmgr.Get(r) // Get current session
if sess != nil {
// Session exists, do something with it.
ctx.Infof("Count: %v", sess.Attr("Count"))
} else {
// No session yet, let's create one and add it:
sess = session.NewSession()
sess.SetAttr("Count", 1)
sessmgr.Add(sess, w)
}
Expired sessions are not automatically removed from the Datastore. To remove expired sessions, the package provides a PurgeExpiredSessFromDSFunc()
function which returns an http.HandlerFunc
. It is recommended to register the returned handler function to a path which then can be defined as a cron job to be called periodically, e.g. in every 30 minutes or so (your choice). As cron handlers may run up to 10 minutes, the returned handler will stop at 8 minutes
to complete safely even if there are more expired, undeleted sessions. It can be registered like this:
http.HandleFunc("/demo/purge", session.PurgeExpiredSessFromDSFunc(""))
Check out the GAE session demo application which shows how it can be used.
cron.yaml file of the demo shows how a cron job can be defined to purge expired sessions.
Check out the GAE session demo application which shows how to use this in action.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论