bugfix: protect field access with lock to avoid possible data race (#5211)
This commit is contained in:
parent
f61065d674
commit
4e481606f7
@ -9,6 +9,7 @@
|
|||||||
- [Fix 5079: only log msg when the channel is not closed](https://github.com/beego/beego/pull/5132)
|
- [Fix 5079: only log msg when the channel is not closed](https://github.com/beego/beego/pull/5132)
|
||||||
- [Fix 4435: Controller SaveToFile remove all temp file](https://github.com/beego/beego/pull/5138)
|
- [Fix 4435: Controller SaveToFile remove all temp file](https://github.com/beego/beego/pull/5138)
|
||||||
- [Fix 5079: Split signalChan into flushChan and closeChan](https://github.com/beego/beego/pull/5139)
|
- [Fix 5079: Split signalChan into flushChan and closeChan](https://github.com/beego/beego/pull/5139)
|
||||||
|
- [Fix 5172: protect field access with lock to avoid possible data race](https://github.com/beego/beego/pull/5210)
|
||||||
|
|
||||||
# v2.0.7
|
# v2.0.7
|
||||||
- [Upgrade github.com/go-kit/kit, CVE-2022-24450](https://github.com/beego/beego/pull/5121)
|
- [Upgrade github.com/go-kit/kit, CVE-2022-24450](https://github.com/beego/beego/pull/5121)
|
||||||
|
|||||||
54
client/cache/README.md
vendored
54
client/cache/README.md
vendored
@ -1,54 +0,0 @@
|
|||||||
## cache
|
|
||||||
|
|
||||||
cache is a Go cache manager. It can use many cache adapters. The repo is inspired by `database/sql` .
|
|
||||||
|
|
||||||
## How to install?
|
|
||||||
|
|
||||||
go get github.com/beego/beego/v2/client/cache
|
|
||||||
|
|
||||||
## What adapters are supported?
|
|
||||||
|
|
||||||
As of now this cache support memory, Memcache and Redis.
|
|
||||||
|
|
||||||
## How to use it?
|
|
||||||
|
|
||||||
First you must import it
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/beego/beego/v2/client/cache"
|
|
||||||
)
|
|
||||||
|
|
||||||
Then init a Cache (example with memory adapter)
|
|
||||||
|
|
||||||
bm, err := cache.NewCache("memory", `{"interval":60}`)
|
|
||||||
|
|
||||||
Use it like this:
|
|
||||||
|
|
||||||
bm.Put("astaxie", 1, 10 * time.Second)
|
|
||||||
bm.Get("astaxie")
|
|
||||||
bm.IsExist("astaxie")
|
|
||||||
bm.Delete("astaxie")
|
|
||||||
|
|
||||||
## Memory adapter
|
|
||||||
|
|
||||||
Configure memory adapter like this:
|
|
||||||
|
|
||||||
{"interval":60}
|
|
||||||
|
|
||||||
interval means the gc time. The cache will check at each time interval, whether item has expired.
|
|
||||||
|
|
||||||
## Memcache adapter
|
|
||||||
|
|
||||||
Memcache adapter use the [gomemcache](http://github.com/bradfitz/gomemcache) client.
|
|
||||||
|
|
||||||
Configure like this:
|
|
||||||
|
|
||||||
{"conn":"127.0.0.1:11211"}
|
|
||||||
|
|
||||||
## Redis adapter
|
|
||||||
|
|
||||||
Redis adapter use the [redigo](http://github.com/gomodule/redigo) client.
|
|
||||||
|
|
||||||
Configure like this:
|
|
||||||
|
|
||||||
{"conn":":6039"}
|
|
||||||
@ -20,15 +20,16 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/couchbase"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/couchbase"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("couchbase", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"http://host:port/, Pool, Bucket"}``)
|
// globalSessions, _ = session.NewManager("couchbase", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"http://host:port/, Pool, Bucket"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package couchbase
|
package couchbase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -105,8 +106,10 @@ func (cs *SessionStore) SessionID(context.Context) string {
|
|||||||
// SessionRelease Write couchbase session with Gob string
|
// SessionRelease Write couchbase session with Gob string
|
||||||
func (cs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (cs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
defer cs.b.Close()
|
defer cs.b.Close()
|
||||||
|
cs.lock.RLock()
|
||||||
bo, err := session.EncodeGob(cs.values)
|
values := cs.values
|
||||||
|
cs.lock.RUnlock()
|
||||||
|
bo, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,10 @@ func (ls *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease save session values to ledis
|
// SessionRelease save session values to ledis
|
||||||
func (ls *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (ls *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(ls.values)
|
ls.lock.RLock()
|
||||||
|
values := ls.values
|
||||||
|
ls.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,15 +20,16 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/memcache"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/memcache"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("memcache", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:11211"}``)
|
// globalSessions, _ = session.NewManager("memcache", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:11211"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package memcache
|
package memcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -96,7 +97,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease save session values to memcache
|
// SessionRelease save session values to memcache
|
||||||
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(rs.values)
|
rs.lock.RLock()
|
||||||
|
values := rs.values
|
||||||
|
rs.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
// go install github.com/go-sql-driver/mysql
|
// go install github.com/go-sql-driver/mysql
|
||||||
//
|
//
|
||||||
// mysql session support need create table as sql:
|
// mysql session support need create table as sql:
|
||||||
|
//
|
||||||
// CREATE TABLE `session` (
|
// CREATE TABLE `session` (
|
||||||
// `session_key` char(64) NOT NULL,
|
// `session_key` char(64) NOT NULL,
|
||||||
// `session_data` blob,
|
// `session_data` blob,
|
||||||
@ -28,15 +29,16 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/mysql"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/mysql"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]"}``)
|
// globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package mysql
|
package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -109,7 +111,10 @@ func (st *SessionStore) SessionID(context.Context) string {
|
|||||||
// must call this method to save values to database.
|
// must call this method to save values to database.
|
||||||
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
defer st.c.Close()
|
defer st.c.Close()
|
||||||
b, err := session.EncodeGob(st.values)
|
st.lock.RLock()
|
||||||
|
values := st.values
|
||||||
|
st.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
//
|
//
|
||||||
// go install github.com/lib/pq
|
// go install github.com/lib/pq
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// needs this table in your database:
|
// needs this table in your database:
|
||||||
//
|
//
|
||||||
// CREATE TABLE session (
|
// CREATE TABLE session (
|
||||||
@ -35,18 +34,18 @@
|
|||||||
// SessionSavePath = "user=a password=b dbname=c sslmode=disable"
|
// SessionSavePath = "user=a password=b dbname=c sslmode=disable"
|
||||||
// SessionName = session
|
// SessionName = session
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/postgresql"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/postgresql"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("postgresql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"user=pqgotest dbname=pqgotest sslmode=verify-full"}``)
|
// globalSessions, _ = session.NewManager("postgresql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"user=pqgotest dbname=pqgotest sslmode=verify-full"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package postgres
|
package postgres
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -115,7 +114,10 @@ func (st *SessionStore) SessionID(context.Context) string {
|
|||||||
// must call this method to save values to database.
|
// must call this method to save values to database.
|
||||||
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
defer st.c.Close()
|
defer st.c.Close()
|
||||||
b, err := session.EncodeGob(st.values)
|
st.lock.RLock()
|
||||||
|
values := st.values
|
||||||
|
st.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,15 +20,16 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/redis"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/redis"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``)
|
// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -100,7 +101,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease save session values to redis
|
// SessionRelease save session values to redis
|
||||||
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(rs.values)
|
rs.lock.RLock()
|
||||||
|
values := rs.values
|
||||||
|
rs.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,15 +20,16 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/redis_cluster"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/redis_cluster"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// globalSessions, _ = session.NewManager("redis_cluster", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070;127.0.0.1:7071"}``)
|
// globalSessions, _ = session.NewManager("redis_cluster", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070;127.0.0.1:7071"}``)
|
||||||
// go globalSessions.GC()
|
// go globalSessions.GC()
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
package redis_cluster
|
package redis_cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -100,7 +101,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease save session values to redis_cluster
|
// SessionRelease save session values to redis_cluster
|
||||||
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(rs.values)
|
rs.lock.RLock()
|
||||||
|
values := rs.values
|
||||||
|
rs.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,10 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/server/web/session/redis_sentinel"
|
//
|
||||||
// "github.com/beego/beego/v2/server/web/session"
|
// _ "github.com/beego/beego/v2/server/web/session/redis_sentinel"
|
||||||
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
|
//
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -101,7 +103,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease save session values to redis_sentinel
|
// SessionRelease save session values to redis_sentinel
|
||||||
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(rs.values)
|
rs.lock.RLock()
|
||||||
|
values := rs.values
|
||||||
|
rs.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,9 +75,11 @@ func (st *CookieSessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease Write cookie session to http response cookie
|
// SessionRelease Write cookie session to http response cookie
|
||||||
func (st *CookieSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (st *CookieSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
st.lock.Lock()
|
st.lock.RLock()
|
||||||
encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values)
|
values := st.values
|
||||||
st.lock.Unlock()
|
st.lock.RUnlock()
|
||||||
|
encodedCookie, err := encodeCookie(
|
||||||
|
cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, values)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cookie := &http.Cookie{
|
cookie := &http.Cookie{
|
||||||
Name: cookiepder.config.CookieName,
|
Name: cookiepder.config.CookieName,
|
||||||
@ -110,11 +112,12 @@ type CookieProvider struct {
|
|||||||
// SessionInit Init cookie session provider with max lifetime and config json.
|
// SessionInit Init cookie session provider with max lifetime and config json.
|
||||||
// maxlifetime is ignored.
|
// maxlifetime is ignored.
|
||||||
// json config:
|
// json config:
|
||||||
// securityKey - hash string
|
//
|
||||||
// blockKey - gob encode hash string. it's saved as aes crypto.
|
// securityKey - hash string
|
||||||
// securityName - recognized name in encoded cookie string
|
// blockKey - gob encode hash string. it's saved as aes crypto.
|
||||||
// cookieName - cookie name
|
// securityName - recognized name in encoded cookie string
|
||||||
// maxage - cookie max life time.
|
// cookieName - cookie name
|
||||||
|
// maxage - cookie max life time.
|
||||||
func (pder *CookieProvider) SessionInit(ctx context.Context, maxlifetime int64, config string) error {
|
func (pder *CookieProvider) SessionInit(ctx context.Context, maxlifetime int64, config string) error {
|
||||||
pder.config = &cookieConfig{}
|
pder.config = &cookieConfig{}
|
||||||
err := json.Unmarshal([]byte(config), pder.config)
|
err := json.Unmarshal([]byte(config), pder.config)
|
||||||
|
|||||||
@ -205,7 +205,10 @@ func (s *SessionStore) SessionID(context.Context) string {
|
|||||||
|
|
||||||
// SessionRelease Store the keyvalues into ssdb
|
// SessionRelease Store the keyvalues into ssdb
|
||||||
func (s *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
func (s *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
|
||||||
b, err := session.EncodeGob(s.values)
|
s.lock.RLock()
|
||||||
|
values := s.values
|
||||||
|
s.lock.RUnlock()
|
||||||
|
b, err := session.EncodeGob(values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user