github.com/astaxie/beego@v1.12.3/session/mysql/sess_mysql.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package mysql for session provider 16 // 17 // depends on github.com/go-sql-driver/mysql: 18 // 19 // go install github.com/go-sql-driver/mysql 20 // 21 // mysql session support need create table as sql: 22 // CREATE TABLE `session` ( 23 // `session_key` char(64) NOT NULL, 24 // `session_data` blob, 25 // `session_expiry` int(11) unsigned NOT NULL, 26 // PRIMARY KEY (`session_key`) 27 // ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 28 // 29 // Usage: 30 // import( 31 // _ "github.com/astaxie/beego/session/mysql" 32 // "github.com/astaxie/beego/session" 33 // ) 34 // 35 // func init() { 36 // globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]"}``) 37 // go globalSessions.GC() 38 // } 39 // 40 // more docs: http://beego.me/docs/module/session.md 41 package mysql 42 43 import ( 44 "database/sql" 45 "net/http" 46 "sync" 47 "time" 48 49 "github.com/astaxie/beego/session" 50 // import mysql driver 51 _ "github.com/go-sql-driver/mysql" 52 ) 53 54 var ( 55 // TableName store the session in MySQL 56 TableName = "session" 57 mysqlpder = &Provider{} 58 ) 59 60 // SessionStore mysql session store 61 type SessionStore struct { 62 c *sql.DB 63 sid string 64 lock sync.RWMutex 65 values map[interface{}]interface{} 66 } 67 68 // Set value in mysql session. 69 // it is temp value in map. 70 func (st *SessionStore) Set(key, value interface{}) error { 71 st.lock.Lock() 72 defer st.lock.Unlock() 73 st.values[key] = value 74 return nil 75 } 76 77 // Get value from mysql session 78 func (st *SessionStore) Get(key interface{}) interface{} { 79 st.lock.RLock() 80 defer st.lock.RUnlock() 81 if v, ok := st.values[key]; ok { 82 return v 83 } 84 return nil 85 } 86 87 // Delete value in mysql session 88 func (st *SessionStore) Delete(key interface{}) error { 89 st.lock.Lock() 90 defer st.lock.Unlock() 91 delete(st.values, key) 92 return nil 93 } 94 95 // Flush clear all values in mysql session 96 func (st *SessionStore) Flush() error { 97 st.lock.Lock() 98 defer st.lock.Unlock() 99 st.values = make(map[interface{}]interface{}) 100 return nil 101 } 102 103 // SessionID get session id of this mysql session store 104 func (st *SessionStore) SessionID() string { 105 return st.sid 106 } 107 108 // SessionRelease save mysql session values to database. 109 // must call this method to save values to database. 110 func (st *SessionStore) SessionRelease(w http.ResponseWriter) { 111 defer st.c.Close() 112 b, err := session.EncodeGob(st.values) 113 if err != nil { 114 return 115 } 116 st.c.Exec("UPDATE "+TableName+" set `session_data`=?, `session_expiry`=? where session_key=?", 117 b, time.Now().Unix(), st.sid) 118 } 119 120 // Provider mysql session provider 121 type Provider struct { 122 maxlifetime int64 123 savePath string 124 } 125 126 // connect to mysql 127 func (mp *Provider) connectInit() *sql.DB { 128 db, e := sql.Open("mysql", mp.savePath) 129 if e != nil { 130 return nil 131 } 132 return db 133 } 134 135 // SessionInit init mysql session. 136 // savepath is the connection string of mysql. 137 func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error { 138 mp.maxlifetime = maxlifetime 139 mp.savePath = savePath 140 return nil 141 } 142 143 // SessionRead get mysql session by sid 144 func (mp *Provider) SessionRead(sid string) (session.Store, error) { 145 c := mp.connectInit() 146 row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid) 147 var sessiondata []byte 148 err := row.Scan(&sessiondata) 149 if err == sql.ErrNoRows { 150 c.Exec("insert into "+TableName+"(`session_key`,`session_data`,`session_expiry`) values(?,?,?)", 151 sid, "", time.Now().Unix()) 152 } 153 var kv map[interface{}]interface{} 154 if len(sessiondata) == 0 { 155 kv = make(map[interface{}]interface{}) 156 } else { 157 kv, err = session.DecodeGob(sessiondata) 158 if err != nil { 159 return nil, err 160 } 161 } 162 rs := &SessionStore{c: c, sid: sid, values: kv} 163 return rs, nil 164 } 165 166 // SessionExist check mysql session exist 167 func (mp *Provider) SessionExist(sid string) bool { 168 c := mp.connectInit() 169 defer c.Close() 170 row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid) 171 var sessiondata []byte 172 err := row.Scan(&sessiondata) 173 return err != sql.ErrNoRows 174 } 175 176 // SessionRegenerate generate new sid for mysql session 177 func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { 178 c := mp.connectInit() 179 row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid) 180 var sessiondata []byte 181 err := row.Scan(&sessiondata) 182 if err == sql.ErrNoRows { 183 c.Exec("insert into "+TableName+"(`session_key`,`session_data`,`session_expiry`) values(?,?,?)", oldsid, "", time.Now().Unix()) 184 } 185 c.Exec("update "+TableName+" set `session_key`=? where session_key=?", sid, oldsid) 186 var kv map[interface{}]interface{} 187 if len(sessiondata) == 0 { 188 kv = make(map[interface{}]interface{}) 189 } else { 190 kv, err = session.DecodeGob(sessiondata) 191 if err != nil { 192 return nil, err 193 } 194 } 195 rs := &SessionStore{c: c, sid: sid, values: kv} 196 return rs, nil 197 } 198 199 // SessionDestroy delete mysql session by sid 200 func (mp *Provider) SessionDestroy(sid string) error { 201 c := mp.connectInit() 202 c.Exec("DELETE FROM "+TableName+" where session_key=?", sid) 203 c.Close() 204 return nil 205 } 206 207 // SessionGC delete expired values in mysql session 208 func (mp *Provider) SessionGC() { 209 c := mp.connectInit() 210 c.Exec("DELETE from "+TableName+" where session_expiry < ?", time.Now().Unix()-mp.maxlifetime) 211 c.Close() 212 } 213 214 // SessionAll count values in mysql session 215 func (mp *Provider) SessionAll() int { 216 c := mp.connectInit() 217 defer c.Close() 218 var total int 219 err := c.QueryRow("SELECT count(*) as num from " + TableName).Scan(&total) 220 if err != nil { 221 return 0 222 } 223 return total 224 } 225 226 func init() { 227 session.Register("mysql", mysqlpder) 228 }