当你使用一个应用程序,你打开它,做了一些改变,然后关闭它。这就像一个会话。计算机知道你是谁。它知道你什么时候开始这个程序,什么什么时候关闭。但是在互联网上,这是一个问题:web服务器不知道你是谁,也不知道你做什么,因为HTTP不能保持状态。

Session 变量通过存储要在多个页面上使用的用户信息(例如用户名,喜欢的颜色等)来解决此问题。默认情况下,Session 变量会一直存在,直到浏览器关闭。

因此,Session 变量保存有关一个用户的信息,并且可用于一个应用程序中的所有页面。

Tip:如果你想要持久化存储,你可以存储数据到数据库中。

Iris 在 iris/sessions 子包中有自己的会话实现和会话管理。你只需导入这个包就能使用了。

一个会话通过 Session 对象的 Start 函数开始,Session 对象是通过 New 函数创建的,这个函数会返回一个 Sessoin

Session 变量通过 Session.Set 方法设置,通过 Session.Get 方法取回。使用 Session.Delete 删除一个变量。要删除整个会话并使之无效,请使用 Session.Destroy 方法。

session 管理器通过 New 方法创建的。

  1. import "github.com/kataras/iris/v12/sessions
  2. sess := sessions.New(sessions.Config{Cookie: "cookieName", ...})

Config

  1. Config struct {
  2. // session 的 cookie名字,例如:"mysessionid"
  3. // 默认为 "irissessionid"
  4. Cookie string
  5. // 如果服务器通过 TLS 运行,CookieSecureTLS 设置为true,
  6. // 你需要把 session的cookie的 "Secure" 字段设置为 true。
  7. //
  8. // 记住:为了正常工作用户应该指定"Decode" 配置字段。
  9. // 建议:您不需要将此字段设置为true,只需在_examples文件夹中提供
  10. // example的第三方库(例如secure cookie)填充Encode和Decode字段即可。
  11. //
  12. // 默认为 false
  13. CookieSecureTLS bool
  14. // AllowReclaim 将允许在想用的请求处理器中清除然后重新开始一个session
  15. // 它所做的只是在“Destroy”时删除“Request”和“ ResponseWriter”的cookie,
  16. // 或者在“Start”时将新cookie添加到“请求”。
  17. //
  18. // 默认为 false
  19. AllowReclaim bool
  20. // 当cookie值不为nil时编码此cookie值(config.Cookie字段指定的值)。
  21. // 接受cookie的名字为第一个参数,第二个参数为服务器产生的session id。
  22. // 返回新的session id,如果发生错误,session id将置为空,这是无效的。
  23. //
  24. // 提示:错误将不会打印,因此你应该清楚你所做的。
  25. // 记住:如果你使用 AES,它仅支持key的大小为16,24,或者32 bytes。
  26. // 你要么提供准确的值或者从你键入的内容中得到key
  27. //
  28. // 默认为nil
  29. Encode func(cookieName string, value interface{}) (string, error)
  30. // 如果cookie值不为nil则对其解码
  31. // 第一个参数为cookie的名字(config.Cookie字段指定的值),
  32. // 第二个参数为客户端的cookie值(也就是被编码后的 session id),
  33. // 当操作失败时返回错误
  34. //
  35. // 提示:错误将不会打印,因此你应该清楚你所做的。
  36. // 记住:如果你使用 AES,它仅支持key的大小为16,24,或者32 bytes。=
  37. // 你要么提供准确的值或者从你键入的内容中得到key
  38. //
  39. // 默认为nil
  40. Decode func(cookieName string, cookieValue string, v interface{}) error
  41. // Defaults to nil.
  42. // Encoding 功能与 Encode和Decode类似,但是接受一个实例,
  43. // 这个实例实现了 "CookieEncoder" 接口(Encode和Decode方法)。
  44. //
  45. // 默认为nil
  46. Encoding Encoding
  47. // 指定cookie必须的生存时间(created_time.Add(Expires)),
  48. // 如果你想要在浏览器关闭时删除cookie,就设置为 -1。
  49. // 0 意味着没有过期时间(24年),
  50. // -1 意味着浏览器关闭时删除
  51. // >0 就是指定session 的cookie生存期(time.Duration类型)。
  52. Expires time.Duration
  53. // SessionIDGenerator 可以设置一个函数,用于返回一个唯一的session id。
  54. // 默认将使用uuid包来生成session id,但是开发者可以通过指定这个字段来改变这个行为。
  55. SessionIDGenerator func(ctx context.Context) string
  56. // DisableSubdomainPersistence 设置为true时,
  57. // 将不允许你的子域名拥有访问session 的cookie的权利
  58. //
  59. // 默认为false
  60. DisableSubdomainPersistence bool
  61. }

New 返回一个 Sessions 的指针,并拥有这些方法:

  1. // 为特定的请求创建或者取回一个已经存在的session。
  2. Start(ctx iris.Context, cookieOptions ...iris.CookieOption)
  3. // Handler 返回一个session中间件,用以注册到应用程序路由中。
  4. Handler(cookieOptions ...iris.CookieOption) iris.Handler
  5. // 移除session数据和相关cookie。
  6. Destroy(ctx context.Context)
  7. // 移除服务器端内存(和已注册的数据库)中的所有session。
  8. // 客户端的session cookie将依然存在,但是它将会被下个请求重新设置
  9. DestroyAll()
  10. // DestroyByID 移除服务器端内存(和已注册的数据库)中的session 条目。
  11. // 客户端的session cookie将依然存在,但是它将会被下个请求重新设置
  12. // 使用这个很安全,即使你不确定这个id对应的session是否存在。
  13. // 提示:sid应该是原始的数据(即从存储中获取),不是已经解码的。
  14. DestroyByID(sessID string)
  15. // OnDestroy 注册一个或者多个移除监听者。
  16. // 当一个服务端或者客户端(cookie)的session被移除,将会触发监听者。
  17. // 记住如果一个监听者被阻塞,会话管理器将都会延迟,
  18. // 在侦听器中使用goroutine避免这种情况。
  19. OnDestroy(callback func(sid string))
  20. // ShiftExpiration 通过session默认的超时配置,将会话的过期日期更改到新的日期
  21. // 如果使用数据库保存session将会抛出 "ErrNotImplemented" 错误,因为数据库不支持这个特性。
  22. ShiftExpiration(ctx iris.Context,
  23. cookieOptions ...iris.CookieOption) error
  24. // UpdateExpiration 通过 "expires" 这个超时值将session的超时日期改为新的日期。
  25. // 如果更新一个不存在或者无效的session条目,将会返回 "ErrNotFound" 异常。
  26. // 如果使用数据库保存session将会抛出 "ErrNotImplemented" 错误,因为数据库不支持这个特性。
  27. UpdateExpiration(ctx iris.Context, expires time.Duration
  28. cookieOptions ...iris.CookieOption) error
  29. // UseDatabase 添加一个session数据库到session管理器中,
  30. // 会话数据库没有写访问权
  31. UseDatabase(db Database)

这里的 CookieOption 仅仅是一个 func(*http.Cookie) 函数,允许自定义配置cookie的属性。

Start 方法返回一个 Session 指针值,这个指针有自己的方法来为每个session工作。

  1. func (ctx iris.Context) {
  2. session := sess.Start(ctx)
  3. // 返回session的id
  4. .ID() string
  5. // 如果这个session是在当前处理流程中创建,将返回true
  6. .IsNew() bool
  7. // 根据会话的键,填充相应的值
  8. .Set(key string, value interface{})
  9. // 根据会话的键,填充相应的值。
  10. // 与 Set 不同,当使用 Get 时,无法改变输出值
  11. // 一个不可变的条目只能通过 SetImmutable 改变,Set将不能工作
  12. // 如果条目是不可变的,这将是安全的。
  13. // 谨慎使用,它比 Set 慢
  14. .SetImmutable(key string, value interface{})
  15. // 获取所有值的一个备份
  16. .GetAll() map[string]interface{}
  17. // 返回这个session保存的值的总数
  18. .Len() int
  19. // 移除key对应的条目,如果有条目移除则返回true
  20. .Delete(key string) bool
  21. // 移除所有的session条目
  22. .Clear()
  23. // 返回key对应的值
  24. .Get(key string) interface{}
  25. // 与Get类似,但是返回的是值的字符串表示形式。
  26. // 如果不存在key,返回空字符串。
  27. .GetString(key string) string
  28. // 与Get类似,但是返回的是值的字符串表示形式。
  29. // 如果不存在key,返回defaultValue定义的默认值。
  30. .GetStringDefault(key string, defaultValue string) string
  31. // 与Get类似,但是返回的是值的int表示形式。
  32. // 如果不存在key,返回-1和一个非nil的错误
  33. .GetInt(key string) (int, error)
  34. // 与Get类似,但是返回的是值的int表示形式。
  35. // 如果不存在key,返回defaultValue定义的默认值。
  36. .GetIntDefault(key string, defaultValue int) int
  37. // 将保存的key的值+n,
  38. // 如果key不存在,则设置key的值为n
  39. // 返回增加后的值
  40. .Increment(key string, n int) (newValue int)
  41. // 将保存的key的值-n,
  42. // 如果key不存在,则设置key的值为n
  43. // 返回减少后的值
  44. .Decrement(key string, n int) (newValue int)
  45. // 与Get类似,但是返回的是值的int64表示形式。
  46. // 如果不存在key,返回-1和一个非nil的错误
  47. .GetInt64(key string) (int64, error)
  48. // 与Get类似,但是返回的是值的int64表示形式。
  49. // 如果不存在key,返回defaultValue定义的默认值。
  50. .GetInt64Default(key string, defaultValue int64) int64
  51. // 与Get类似,但是返回的是值的float32表示形式。
  52. // 如果不存在key,返回-1和一个非nil的错误
  53. .GetFloat32(key string) (float32, error)
  54. // 与Get类似,但是返回的是值的float32表示形式。
  55. // 如果不存在key,返回defaultValue定义的默认值。
  56. .GetFloat32Default(key string, defaultValue float32) float32
  57. // 与Get类似,但是返回的是值的float64表示形式。
  58. // 如果不存在key,返回-1和一个非nil的错误
  59. .GetFloat64(key string) (float64, error)
  60. // 与Get类似,但是返回的是值的float64表示形式。
  61. // 如果不存在key,返回defaultValue定义的默认值。
  62. .GetFloat64Default(key string, defaultValue float64) float64
  63. // 与Get类似,但是返回的是值的boolean表示形式。
  64. // 如果不存在key,返回-1和一个非nil的错误
  65. .GetBoolean(key string) (bool, error)
  66. // 与Get类似,但是返回的是值的boolean表示形式。
  67. // 如果不存在key,返回defaultValue定义的默认值。
  68. .GetBooleanDefault(key string, defaultValue bool) bool
  69. // 通过key设置一个即时信息。
  70. // 即时信息是为了保存一个信息到session中,这样同一个用户的多个请求都能获取到这个信息。
  71. // 当这个信息展示给用户后就会被移除。
  72. // 即时信息通常用于与HTTP重定向组合,
  73. // 因为这种情况下是没有视图的,信息只能在重定向后展示给用户。
  74. //
  75. // 一条即时信息拥有它的key和内容。
  76. // 这是一个有关联的数组。
  77. // 名字是一个字符串:通常为"notice","sucess","error",但是可以为任何string。
  78. // 内容通常是stirng。如果你想直接显示它,你可以放一些HTML标签在信息中。
  79. // 也可以放置一个数组或者数组:将会被序列化,然后以字符串类型保存。
  80. //
  81. // 即时信息可以是用哪个 SetFlash 方法设置。
  82. // 例如,你想要通知用户他的改变成功保存了,
  83. // 你可以在你的处理中添加下面一行:SetFlash("success", "data saved")
  84. // 在这个例子中我们使用key"success",如果你想要定义更多即时信息,你可以使用不同的key。
  85. .SetFlash(key string, value interface{})
  86. // 如果这个session有可用的即时信息将返回true
  87. .HasFlash() bool
  88. // GetFlashes 返回所有的即时信息的值,使用的是 map[string]interface{} 格式。
  89. // 记住:这将导致在同一用户的下一个请求上删除所有当前的即时消息。
  1. .GetFlashes() map[string]interface{}
  1. // PeekFlash 返回key对应的暂存的即时信息。
  2. // 与GetFlash不同,这个信息在下个请求时可用,除非使用GetFlashes或者GetFlash
  3. .PeekFlash(key string) interface{}
  4. // GetFlash返回key对应的存储的即时信息,并且在下个请求中移除这个即时信息。
  5. // 检查即时信息我们使用 HashFlash() 方法,获得即时信息我们使用GetFlash()方法。
  6. // GetFlashes() 获取所有的信息。
  7. // 获取信息并从session删除,这意味着一条消息只能在提供给用户的第一个页面上显示。
  8. .GetFlash(key string) interface{}
  9. // 与GetFlash类似,但是返回的是string表示形式,
  10. // 如果key不存在,则返回空string
  11. .GetFlashString(key string) string
  12. // 与GetFlash类似,但是返回的是string表示形式,
  13. // 如果key不存在,则返回defaultValue指定的默认值
  14. .GetFlashStringDefault(key string, defaultValue string) string
  15. // 删除key这个即时信息
  16. .DeleteFlash(key string)
  17. // 移除所有的即时信息
  18. .ClearFlashes()
  19. // "摧毁"这个session,它移除session的值和所有即时信息。
  20. // session条目将会从服务器中移除,注册的session数据库也会被通知删除。
  21. // 记住这个方法不会移除客户端的cookie,如果附上新的session客户端的cookie将会被重置。
  22. // 使用会话管理器的 "Destroy(ctx)" 来移除cookie。
  23. .Destroy()
  24. }

示例:

在这里例子中我们将允许通过验证的用户访问 /secret 的隐秘信息。为了有访问的权限,我们首先需要访问 /login 来获取一个可用的session 的 cookie,使它登录成功。另外也可以访问 /logout 撤销访问权限。

  1. // sessions.go
  2. package main
  3. import (
  4. "github.com/kataras/iris/v12"
  5. "github.com/kataras/iris/v12/sessions"
  6. )
  7. var (
  8. cookieNameForSessionID = "mycookiesessionnameid"
  9. sess = sessions.New(sessions.Config{Cookie: cookieNameForSessionID})
  10. )
  11. func secret(ctx iris.Context) {
  12. // Check if user is authenticated
  13. if auth, _ := sess.Start(ctx).GetBoolean("authenticated"); !auth {
  14. ctx.StatusCode(iris.StatusForbidden)
  15. return
  16. }
  17. // Print secret message
  18. ctx.WriteString("The cake is a lie!")
  19. }
  20. func login(ctx iris.Context) {
  21. session := sess.Start(ctx)
  22. // Authentication goes here
  23. // ...
  24. // Set user as authenticated
  25. session.Set("authenticated", true)
  26. }
  27. func logout(ctx iris.Context) {
  28. session := sess.Start(ctx)
  29. // Revoke users authentication
  30. session.Set("authenticated", false)
  31. // Or to remove the variable:
  32. session.Delete("authenticated")
  33. // Or destroy the whole session:
  34. session.Destroy()
  35. }
  36. func main() {
  37. app := iris.New()
  38. app.Get("/secret", secret)
  39. app.Get("/login", login)
  40. app.Get("/logout", logout)
  41. app.Run(iris.Addr(":8080"))
  42. }

访问:

  1. $ go run sessions.go
  2. $ curl -s http://localhost:8080/secret
  3. Forbidden
  4. $ curl -s -I http://localhost:8080/login
  5. Set-Cookie: mysessionid=MTQ4NzE5Mz...
  6. $ curl -s --cookie "mysessionid=MTQ4NzE5Mz..." http://localhost:8080/secret
  7. The cake is a lie!