###导航:
Leafveingo启动
->
初始化HttpSessionManager(包括自动GC)->
请求获取session->
操作Cookie->
得到session->
session数据存储或其他操作->
可手动进行session的销毁->
GC自动清理操作
设置session manager需要通过Leafveingo进行获取
leafvein.HttpSessionManager()
,还有一些基本的设置是由Leafveingo来进行处理的,以下是列出设置的API:HttpSessionManager的设置
// 为方便文档编写设置一个设置为变量进行调用演示 sessionManager := leafvein.HttpSessionManager() // cookie设置 Secure 默认 false sessionManager.CookieSecure = bool // cookie设置 MaxAge 默认 0 sessionManager.CookieMaxAge = int // cookie token 生成的 hmac 的哈希类型设置,默认 sha256.New // 也可以选择 sha1.New sessionManager.CookieTokenHash = func() hash.Hash // cookie token 随机数生成的长度,默认 48位 sessionManager.CookieTokenRandLen = int // cookie token 最大有效时间,默认 300 second // 如果超出了有效时间则会自动生成另外一个cookie token,这个不影响HttpSession的使用 // 只是为了cookie的安全设置的一个机制。 sessionManager.CookieTokenMaxlifeTime = int32 // 设置CG HttpSession清理的间隔时间,每段时间会进行一次HttpSession的清理 // @second 秒单位,大于或等于60m sessionManager.SetScanGCTime(second int64) // 设置临时HttpSession的最大有效时间,主要是针对第一次请求创建HttpSession所用, // 主要为了避免垃圾HttpSession的创建,有些访问了一次并且创建了HttpSession就离 // 开了,或则Cookie无法写入时,在或者一些人的并发攻击产生大量的HttpSession所使 // 用的一个机制,在第二次访问的时候就会设置会原来的时间。 // 创建一个HttpSession最小大约占用136 bit // // 避免cookie无法写入时,使用一个临时短暂最大有效时间来控制session的清理。 // 再第二次请求时如果cookie能够获取得到将还原调用者设置session的最大有效时间。 // @second 秒单位,大于或等于60m sessionManager.SetTempSessMaxlifeTime(second int32) // 设置全局的token key,默认是使用 crypto/rand 进行生成的随机数 sessionManager.SetGlobalTokenKey(key []byte) // 设置session id的生成规则,默认是SIDTypeRandomUUID随机数的UUID // @ t SIDTypeRandomUUID or SIDTypeIPUUID // @ urlIPAPi 如果选择SIDTypeRandomUUID可以直接设置为 "" 空。 // 如果选择SIDTypeIPUUID,可以选择性的设置获取ip的URL地址,传递 "" 空则使用默认地址处理。 // 也可以根据自己需求,设置url, url必须能直接获取得到网络的IP信息不需要任何解析操作。 // 由于IPUUID需要连接网络,出现获取不了或解析不了IP的情况下会抛出异常(panic) sessionManager.SetSIDType(t SIDType, urlIPApi string) // HttpSession将要销毁时调用触发的函数 // 传递的session 是一个复制品,可以根据存储的数据或则session id进行一些业务逻辑操作。 sessionManager.AddSessionWillInvalidateHandlerFunc(handlerFunc func(session HttpSession))
Leafveingo对session的设置
// 设置是否开启session进行使用 leafvein.SetIsUseSession(bool) // 首先需要开启session的使用。 // 设置Leafveingo启动时是否开启自动GC清理无效session的操作。 // 如果设置为false需要手动进行GC清理操作,即便是手动进行HttpSession // 的销毁也无法将HttpSession移除内存。 // *leafvein.HttpSessionManager().GC() 手动GC* // 建议开启自动清理工作,默认为true leafvein.SetIsGCSession(bool) // 设置默认创建session时最大的有效时间,默认 1800second(30minute) leafvein.SetSessionMaxlifeTime(second int32)
HttpSession可以直接使用控制器函数参数直接进行接收
func (s *SessionController) Session(sess HttpSession)
也可以手动进行获取,手动获取HttpSession需要使用到HttpContext
func (s *SessionController) Context(contxt *leafveingo.HttpContext){ // cookie token会在一定时间会自动重置,可以选择重置或则不重置,看需求而定 context.Session(true | false) }
HttpSession具体的其他操作可以查看下类型接口:
type HttpSession interface { // 获取session id UID() string // 根据key name获取session存储的数据 Get(key string) (interface{}, bool) // 存储session 数据 Set(key string, v interface{}) // 根据key name删除session数据 Delete(key string) // HttpSession 的最后访问时间 AccessTime() time.Time // HttpSession 访问的IP AccessIP() net.IP // HttpSession 最大有效时间获取和设置 MaxlifeTime() int32 SetMaxlifeTime(second int32) // HttpSession 注销,注销后还未从内存中清除,需要等待GC清理。 Invalidate() // 获取HttpSession IP的访问规则,如果一个session出现多个IP就考虑到可能有问题了。 // map[<ip string>]<ip count> IPAccessRule() map[string]int // 验证form token,这个可以使用HttpContext调用CheckFormToken()进行验证, // 因为需要获取form token设置的内容 CheckFormTokenSignature(signature string) bool // 获取form token签名,这个也可以使用HttpContext来进行操作, // 具体可以查看HttpContext函数。 FormTokenSignature() string }
HttpSession的存储是存储与服务器中,利用cookie存储session的标识字符,这个标识字符就是利用cookie token的安全机制进行效验成功后才能获取得到正确的session存储对象。
cookie token的作用:
- 有效的防止session id被穷举(被穷举出seesion id用户的信息就会被泄漏)
- 有效的防止伪造session欺骗服务器
- 有兴趣可以看下Session fixation attack(会话固定攻击)
关于session的安全:
- 由于session cookie token对于IP没有进行验证,如果cookie被真获取了用户信息就会被窃取。关于验证IP有很多争议,由于在手机访问的时候IP会经常的更换或则路由器被重启IP更改,验证都会失效导致用户的体验性非常的差,还有再一个大局域网中外网IP都是相同的,这时验证就等于没有验证的。
- 对于cookie的劫持Leafveingo已经在Cookie HttpOnly属性中设置为true,这样可以有效的防止javascript读取存储session标识的cookie,不过还会有些安全隐患的。
如何预防呢?目前想到的最有效的机制就是使用Cookie Secure属性的设置,只能使用https访问才能获取得到存储session的cookie。不过Leafveingo对于Cookie Secure默认设置是为false,如果想开启可以设置
sessionManager.CookieSecure = true
,详细可以查看HttpSessionManager的设置
为什么使用form token?
- 防止跨站请求伪造(Cross-site request forgery)
- 表单重复提交
form token与cookie token的区别?
- 两者是不同的关系的,form token主要存储在请求的session中,作用于html form。
- 对于token生成的规则也不相同,由于已经有一层cookie token的保护,所以生成与cookie token相对简单。
使用form token可以利用HttpContext来进行获取,token每次获取都会更改一次token,对于form token生成验证的token存储是有数量限制的,主要利用了LRU Cache(Least Recently Used)模式进行存储,想修改可以到
lv_session.go FORM_TOKEN_SLICE_DEFAULT_LEN
的常量中进行修改需要的存储默认最大长度,不过默认10长度的存储数量已经足够用了,毕竟是利用以旧换新的原则进行替换,旧的token验证就会失效,有兴趣可以看下lv_session.go
的源码的实现原理。使用LRU Cache主要是为了session存储数据的最小原则,毕竟HttpSession存储再服务器的内存中。HttpContext提供了几种获取form token的函数:
// 直接获取token字符串,需要自行操作,获取token进行验证 func (ctx *HttpContext) FormTokenString() string // 返回<input type="hidden" name="formToken" value="xxx" /> func (ctx *HttpContext) FormTokenHTML() string // 利用javseript将token字符串绑定到页面中,可有效防止页面被抓取后获取token func (ctx *HttpContext) FormTokenJavascript() string
HttpContext也提供了form token的验证函数:
// 会以formToken名获取参数进行验证 func (ctx *HttpContext) CheckFormToken() bool // 手动验证,需要自行获取token func (ctx *HttpContext) CheckFormTokenByString(token string) bool
HttpSession是有生命的,在最大的有效时间结束后就会被清理出内存,此时为了业务方便,提供了销毁前的通知调用。
具体操作设置:
// 添加一个接收的函数。
// 传递的session是一个复制品,可以根据存储的数据或则session id进行一些业务逻辑操作。
sessionManager.AddSessionWillInvalidateHandlerFunc(handlerFunc func(sess HttpSession))