进阶 www.iris-go.com 2026-10-20 02:39:14 · 13 阅读

第69章 Session 与 Cookie 安全配置

Sessions & Cookies

本节将从安全角度介绍如何配置 Session cookie 以及通用的 HTTP cookie。

禁用子域名持久性

默认情况下,Iris Sessions Manager 允许在根域名和子域名之间共享 cookie。出于安全考虑,你可能希望使用 DisableSubdomainPersistence 选项来禁用该行为:

go
import "github.com/kataras/iris/v12/sessions"

sess := sessions.New(sessions.Config{
    Cookie: "_iris_session",
    AllowReclaim: true,
    DisableSubdomainPersistence: true,
})
app.UseRouter(sess.Handler())

Sessions Manager 拥有独立的字段用于配置 session cookie 的加密,使其与其他发送给客户端的 cookie 相互独立。你同样可以通过 sess.Handler(...CookieOption) 方法传递 Cookie 选项。

相反,默认的 cookie 选项禁用了跨子域名的 cookie 共享。在处理 HTTP cookie 时,应将 SameSite 选项设置为 http.SameSiteLaxMode,并将 Domain 字段设置为当前站点域名,以便在根域名及其子域名之间启用 cookie 共享。你可以通过将 CookieAllowSubdomains Cookie 选项设置为 Iris 请求 Context 来实现:

go
CookieAllowSubdomains(cookieNames ...string) CookieOption
go
func routeHandler(ctx iris.Context) {
    ctx.SetCookieKV("name", "value", iris.CookieAllowSubdomains())
}
go
import "net/http"
// [...]

func routeHandler(ctx iris.Context) {
    ctx.SetCookie(&iris.Cookie{
        Name: "name",
        Value: "value",
        // Other Fields...
    }, iris.CookieAllowSubdomains())
}

或者通过 AddCookieOptions 实现:

go
func middleware(ctx iris.Context) {
    ctx.AddCookieOptions(iris.CookieAllowSubdomains())
    ctx.Next()
}

func routeHandler(ctx iris.Context) {
    ctx.SetCookieKV("name", "value")
}

func main() {
    app := iris.New()
 
    app.Use(middleware)
    app.Get("/", routeHandler)
    // [...]
}

Cookie 加密

与前面章节中提到的 CSRF 令牌类似,你还可以对通用 cookie 进行安全加固。iris.CookieEncoding 选项用于注册 SecureCookie 实现。

go
CookieEncoding(encoding SecureCookie, cookieNames ...string) CookieOption
SecureCookie 接口定义如下: ```go type SecureCookie interface { Encode(name string, val interface{}) (string, error) Decode(name string, original string, dest interface{}) error } ``` 这个接口与 gorilla/securecookie 包完全兼容,该包简单易用,效果很好。 下面看看如何在 Iris 中集成它,安全地向客户端传输 Cookie。注意,仍然强烈建议让服务器运行在 TLS(https://)之下。 1. 安装 securecookie 包: ```go $ go get -u github.com/gorilla/securecookie ``` 2. 在代码中导入: ```go import "github.com/gorilla/securecookie" ``` 3. securecookie 需要 hash key 和 block key,注意这些密钥不能公开。本例中为了演示我们用随机生成的密钥,但在生产环境中,这些密钥必须在服务器重启后保持不变,否则 Cookie 将无法按预期通过校验: ```go hashKey := securecookie.GenerateRandomKey(64) blockKey := securecookie.GenerateRandomKey(32) ``` 4. 初始化一个 securecookie 实例: ```go s := securecookie.New(hashKey, blockKey) ``` 5. 通过 Iris 的 CookieEncoding Option 注册它。如下所示,根据你需要在何时何地应用 Cookie 选项,有几种不同的方式: ```go import "net/http" // [...] func routeHandler(ctx iris.Context) { ctx.SetCookie(&iris.Cookie{ Name: "name", Value: "value", }, iris.CookieEncoding(s)) } func main() { app := iris.New() app.Get("/", routeHandler) // [...] } ``` 或者通过中间件调用 Context 的 AddCookieOption 方法,为所有 Cookie 统一注册: ```go func routeHandler(ctx iris.Context) { ctx.SetCookie(&iris.Cookie{ Name: "name", Value: "value", }) } func main() { app := iris.New() app.UseRouter(func(ctx iris.Context) { ctx.AddCookieOptions(iris.CookieEncoding(s)) ctx.Next() }) app.Get("/", routeHandler) // [...] } ``` Cookie SameSite 属性 SameSite 属性(定义于 RFC6265)允许开发者声明 Cookie 是否仅限于第一方或同站场景使用。理解此处“站点”的具体含义至关重要。站点由域名后缀及其前紧邻的域名部分共同决定。例如,www.web.dev 属于 web.dev 站点。当用户位于 www.web.dev 并请求 static.web.dev 上的图片时,这属于同站请求。公共后缀列表(Public Suffix List)定义了这些规则,因此不仅包括 .com 等顶级域名,还涵盖 github.io 等服务。这使得 your-project.github.io 和 my-project.github.io 被视为两个独立的站点。如果用户位于 your-project.web.dev 并请求 my-project.github.io 上的图片,则属于跨站请求。 为 Cookie 引入 SameSite 属性提供了三种控制这种行为的方式:可以选择不指定该属性,或使用 Strict 或 Lax 将 Cookie 限制在同站请求中。 SameSite 属性接受以下三个值: Lax:允许在顶层导航时发送,并且会随由第三方网站发起的 GET 请求一同发送。这是现代浏览器的默认值。 Strict:仅在 第一方 上下文中发送,不会随第三方网站发起的请求发送。 None:在所有上下文中发送,即允许跨源传输。None 曾是默认值,但近期浏览器版本已将 Lax 设为默认值,以提供针对跨站请求伪造(CSRF)攻击的较强防护。在最新浏览器版本中,使用 None 必须配合 Secure 属性。 可用的 Cookie SameSite 值: iris.SameSiteDefaultMode iris.SameSiteLaxMode iris.SameSiteStrictMode iris.SameSiteNoneMode 通过 SetCookie 设置 SameSite: go ctx.SetCookie(&iris.Cookie{ Name: ..., Value: ..., SameSite: iris.SameSiteLaxMode, }) 1
2
3
4
5
通过 AddCookieOptions 设置 SameSite: go ctx.AddCookieOptions(iris.CookieSameSite(iris.SameSiteLaxMode)) 1
通过 SetCookieKV 设置 SameSite: go ctx.SetCookieKV(name, value, iris.CookieSameSite(iris.SameSiteLaxMode)) 1

评论 (0)