Session

简介

Session 使你可以在多个请求之间存储用户信息,为本质上无状态的 HTTP 协议提供有状态的体验。这些用户信息在服务器端持久存储。Goravel 提供了一个统一的接口,用于与各种持久存储驱动进行交互。

Configuration

session 配置文件位于 config/session.go。默认驱动是 file,它会把 session 存储在 storage/framework/sessions 目录中。Goravel 允许你通过实现 contracts/session/driver 接口来创建自定义 session 驱动。

注册 Middleware

Goravel 默认情况下未启动 Session 功能,但是框架提供了用于启动会话的中间件。你可以在 app/http/kernel.go 文件中注册 Session 中间件,以将其应用于所有路由,或者将其添加到特定路由中:

import (
  "github.com/goravel/framework/contracts/http"
  "github.com/goravel/framework/session/middleware"
)

func (kernel Kernel) Middleware() []http.Middleware {
  return []http.Middleware{
    middleware.StartSession(),
  }
}

使用 Session

获取数据

你可以使用 Get 方法从 Session 中检索数据。如果值不存在,则返回 nil

value := ctx.Request().Session().Get("key")

你还可以将默认值作为第二个参数传递给 Get 方法。如果会话中不存在指定的键,则返回该值:

value := ctx.Request().Session().Get("key", "default")

获取所有数据

如果你想从会话中检索所有数据,可以使用 All 方法:

data := ctx.Request().Session().All()

获取数据子集

如果你想检索会话数据某些字段,可以使用 Only 方法:

data := ctx.Request().Session().Only([]string{"username", "email"})

确定会话中是否存在项目

确定会话中是否存在项目,你可以使用 Has 方法。如果项目存在且不为 nil,则 Has 方法返回 true

if ctx.Request().Session().Has("user") {
    //
}

确定项目是否存在,即使它是 nil,你可以使用 Exists 方法:

if ctx.Request().Session().Exists("user") {
    //
}

确定项目是否不存在于会话中,你可以使用 Missing 方法:

if ctx.Request().Session().Missing("user") {
    //
}

存储数据

你可以使用 Put 方法将数据存储在会话中:

ctx.Request().Session().Put("key", "value")

检索并删除数据

如果你想从会话中检索项目,然后删除它,可以使用 Pull 方法:

value := ctx.Request().Session().Pull("key")

删除数据

Forget 方法可用于从会话中删除数据。如果你想从会话中删除所有数据,可以使用 Flush 方法:

ctx.Request().Session().Forget("username", "email")

ctx.Request().Session().Flush()

重新生成会话 ID

重新生成会话 ID 通常是为了防止恶意用户利用会话固定攻击来利用你的应用程序。你可以使用 Regenerate 方法重新生成会话 ID:

ctx.Request().Session().Regenerate()

如果你想重新生成会话 ID 并忘记会话中的所有数据,可以使用 Invalidate 方法:

ctx.Request().Session().Invalidate()

然后需要保存新的 session 到 cookie 中:

ctx.Response().Cookie(http.Cookie{
  Name:     ctx.Request().Session().GetName(),
  Value:    ctx.Request().Session().GetID(),
  MaxAge:   facades.Config().GetInt("session.lifetime") * 60,
  Path:     facades.Config().GetString("session.path"),
  Domain:   facades.Config().GetString("session.domain"),
  Secure:   facades.Config().GetBool("session.secure"),
  HttpOnly: facades.Config().GetBool("session.http_only"),
  SameSite: facades.Config().GetString("session.same_site"),
})

闪存数据

闪存数据一种仅在随后的 HTTP 请求中可用的数据,请求结束后将被删除。闪存数据对于存储临时消息(如状态消息)非常有用。你可以使用 Flash 方法将闪存数据存储在会话中:

ctx.Request().Session().Flash("status", "Task was successful!")

如果你希望保留闪存数据以供额外请求使用,可以使用 Reflash 方法:

ctx.Request().Session().Reflash()

如果你希望保留特定的闪存数据以供立即使用,可以使用 Keep 方法:

ctx.Request().Session().Keep("status", "username")

If you would like to keep specific data around for immediate use, you may use the Now method:

如果你希望保留特定数据以供立即使用,可以使用 Now 方法:

ctx.Request().Session().Now("status", "Task was successful!")

会话管理器

构建自定义会话

使用 Session 门面构建自定义会话。Session 门面提供了 BuildSession 方法,它接受一个驱动实例和一个可选的会话 ID,如果你想指定自定义会话 ID:

import "github.com/goravel/framework/facades"

session := facades.Session().BuildSession(driver, "sessionID")

添加自定义会话驱动

实现驱动

要实现自定义会话驱动,驱动必须实现 contracts/session/driver 接口。

// Driver is the interface for Session handlers.
type Driver interface {
  // Close closes the session handler.
  Close() error
  // Destroy destroys the session with the given ID.
  Destroy(id string) error
  // Gc performs garbage collection on the session handler with the given maximum lifetime.
  Gc(maxLifetime int) error
  // Open opens a session with the given path and name.
  Open(path string, name string) error
  // Read reads the session data associated with the given ID.
  Read(id string) (string, error)
  // Write writes the session data associated with the given ID.
  Write(id string, data string) error
}

注册驱动

实现驱动后,你需要在 Goravel 中注册它。你可以在 app/providers/app_service_provider.goboot 方法中调用 Extend 方法:

import "github.com/goravel/framework/contracts/session"

facades.Session().Extend("redis", func() session.Driver {
  return &RedisDriver{}
})

注册了驱动程序以后,你可以通过将会话配置文件中的 driver 选项设置为 redis 或将 SESSION_DRIVER 环境变量设置为 redis 来使用它。

获取驱动实例

使用 Driver 方法从会话管理器中检索驱动实例。它接受一个可选的驱动名称,如果未提供,则返回默认驱动实例:

driver, err := facades.Session().Driver("file")

开始新会话

session := facades.Session().BuildSession(driver)
session.Start()

保存会话数据

session := facades.Session().BuildSession(driver)
session.Start()
session.Save()

将会话附加到请求

session := facades.Session().BuildSession(driver)
session.Start()
ctx.Request().SetSession(session)

检查请求是否有会话

if ctx.Request().HasSession() {
    //
}