Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
张磊
/
FileStorageBeego
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
02c2e162
authored
2013-09-26 18:07:00 +0800
by
astaxie
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Strengthens the session's function
1 parent
59a67720
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
269 additions
and
7 deletions
session/sess_file.go
session/sess_mem.go
session/sess_mysql.go
session/sess_redis.go
session/session.go
session/sess_file.go
View file @
02c2e16
package
session
import
(
"errors"
"io"
"io/ioutil"
"os"
"path"
...
...
@@ -48,6 +50,14 @@ func (fs *FileSessionStore) Delete(key interface{}) error {
return
nil
}
func
(
fs
*
FileSessionStore
)
Flush
()
error
{
fs
.
lock
.
Lock
()
defer
fs
.
lock
.
Unlock
()
fs
.
values
=
make
(
map
[
interface
{}]
interface
{})
fs
.
updatecontent
()
return
nil
}
func
(
fs
*
FileSessionStore
)
SessionID
()
string
{
return
fs
.
sid
}
...
...
@@ -121,6 +131,55 @@ func (fp *FileProvider) SessionGC() {
filepath
.
Walk
(
fp
.
savePath
,
gcpath
)
}
func
(
fp
*
FileProvider
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
SessionStore
,
error
)
{
err
:=
os
.
MkdirAll
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
])),
0777
)
if
err
!=
nil
{
println
(
err
.
Error
())
}
err
=
os
.
MkdirAll
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
])),
0777
)
if
err
!=
nil
{
println
(
err
.
Error
())
}
_
,
err
=
os
.
Stat
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
var
newf
*
os
.
File
if
err
==
nil
{
return
nil
,
errors
.
New
(
"newsid exist"
)
}
else
if
os
.
IsNotExist
(
err
)
{
newf
,
err
=
os
.
Create
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
}
_
,
err
=
os
.
Stat
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
]),
oldsid
))
var
f
*
os
.
File
if
err
==
nil
{
f
,
err
=
os
.
OpenFile
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
]),
oldsid
),
os
.
O_RDWR
,
0777
)
io
.
Copy
(
newf
,
f
)
}
else
if
os
.
IsNotExist
(
err
)
{
newf
,
err
=
os
.
Create
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
}
else
{
return
nil
,
err
}
f
.
Close
()
os
.
Remove
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
])))
os
.
Chtimes
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
),
time
.
Now
(),
time
.
Now
())
var
kv
map
[
interface
{}]
interface
{}
b
,
err
:=
ioutil
.
ReadAll
(
newf
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
b
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
decodeGob
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
}
newf
,
err
=
os
.
OpenFile
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
),
os
.
O_WRONLY
|
os
.
O_CREATE
,
0777
)
ss
:=
&
FileSessionStore
{
f
:
newf
,
sid
:
sid
,
values
:
kv
}
return
ss
,
nil
}
func
gcpath
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
return
err
...
...
session/sess_mem.go
View file @
02c2e16
...
...
@@ -40,6 +40,13 @@ func (st *MemSessionStore) Delete(key interface{}) error {
return
nil
}
func
(
st
*
MemSessionStore
)
Flush
()
error
{
st
.
lock
.
Lock
()
defer
st
.
lock
.
Unlock
()
st
.
value
=
make
(
map
[
interface
{}]
interface
{})
return
nil
}
func
(
st
*
MemSessionStore
)
SessionID
()
string
{
return
st
.
sid
}
...
...
@@ -80,6 +87,29 @@ func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) {
return
nil
,
nil
}
func
(
pder
*
MemProvider
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
SessionStore
,
error
)
{
pder
.
lock
.
RLock
()
if
element
,
ok
:=
pder
.
sessions
[
oldsid
];
ok
{
go
pder
.
SessionUpdate
(
oldsid
)
pder
.
lock
.
RUnlock
()
pder
.
lock
.
Lock
()
element
.
Value
.
(
*
MemSessionStore
)
.
sid
=
sid
pder
.
sessions
[
sid
]
=
element
delete
(
pder
.
sessions
,
oldsid
)
pder
.
lock
.
Unlock
()
return
element
.
Value
.
(
*
MemSessionStore
),
nil
}
else
{
pder
.
lock
.
RUnlock
()
pder
.
lock
.
Lock
()
newsess
:=
&
MemSessionStore
{
sid
:
sid
,
timeAccessed
:
time
.
Now
(),
value
:
make
(
map
[
interface
{}]
interface
{})}
element
:=
pder
.
list
.
PushBack
(
newsess
)
pder
.
sessions
[
sid
]
=
element
pder
.
lock
.
Unlock
()
return
newsess
,
nil
}
return
nil
,
nil
}
func
(
pder
*
MemProvider
)
SessionDestroy
(
sid
string
)
error
{
pder
.
lock
.
Lock
()
defer
pder
.
lock
.
Unlock
()
...
...
session/sess_mysql.go
View file @
02c2e16
...
...
@@ -50,6 +50,14 @@ func (st *MysqlSessionStore) Delete(key interface{}) error {
return
nil
}
func
(
st
*
MysqlSessionStore
)
Flush
()
error
{
st
.
lock
.
Lock
()
defer
st
.
lock
.
Unlock
()
st
.
values
=
make
(
map
[
interface
{}]
interface
{})
st
.
updatemysql
()
return
nil
}
func
(
st
*
MysqlSessionStore
)
SessionID
()
string
{
return
st
.
sid
}
...
...
@@ -108,6 +116,28 @@ func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
return
rs
,
nil
}
func
(
mp
*
MysqlProvider
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
SessionStore
,
error
)
{
c
:=
mp
.
connectInit
()
row
:=
c
.
QueryRow
(
"select session_data from session where session_key=?"
,
oldsid
)
var
sessiondata
[]
byte
err
:=
row
.
Scan
(
&
sessiondata
)
if
err
==
sql
.
ErrNoRows
{
c
.
Exec
(
"insert into session(`session_key`,`session_data`,`session_expiry`) values(?,?,?)"
,
oldsid
,
""
,
time
.
Now
()
.
Unix
())
}
c
.
Exec
(
"update session set `session_key`=? where session_key=?"
,
sid
,
oldsid
)
var
kv
map
[
interface
{}]
interface
{}
if
len
(
sessiondata
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
decodeGob
(
sessiondata
)
if
err
!=
nil
{
return
nil
,
err
}
}
rs
:=
&
MysqlSessionStore
{
c
:
c
,
sid
:
sid
,
values
:
kv
}
return
rs
,
nil
}
func
(
mp
*
MysqlProvider
)
SessionDestroy
(
sid
string
)
error
{
c
:=
mp
.
connectInit
()
c
.
Exec
(
"DELETE FROM session where session_key=?"
,
sid
)
...
...
session/sess_redis.go
View file @
02c2e16
...
...
@@ -35,6 +35,11 @@ func (rs *RedisSessionStore) Delete(key interface{}) error {
return
err
}
func
(
rs
*
RedisSessionStore
)
Flush
()
error
{
_
,
err
:=
rs
.
c
.
Do
(
"DEL"
,
rs
.
sid
)
return
err
}
func
(
rs
*
RedisSessionStore
)
SessionID
()
string
{
return
rs
.
sid
}
...
...
@@ -99,6 +104,16 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
return
rs
,
nil
}
func
(
rp
*
RedisProvider
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
SessionStore
,
error
)
{
c
:=
rp
.
connectInit
()
if
str
,
err
:=
redis
.
String
(
c
.
Do
(
"HGET"
,
oldsid
,
oldsid
));
err
!=
nil
||
str
==
""
{
c
.
Do
(
"HSET"
,
oldsid
,
oldsid
,
rp
.
maxlifetime
)
}
c
.
Do
(
"RENAME"
,
oldsid
,
sid
)
rs
:=
&
RedisSessionStore
{
c
:
c
,
sid
:
sid
}
return
rs
,
nil
}
func
(
rp
*
RedisProvider
)
SessionDestroy
(
sid
string
)
error
{
c
:=
rp
.
connectInit
()
c
.
Do
(
"DEL"
,
sid
)
...
...
session/session.go
View file @
02c2e16
package
session
import
(
"crypto/hmac"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
"net/http"
...
...
@@ -16,11 +20,13 @@ type SessionStore interface {
Delete
(
key
interface
{})
error
//delete session value
SessionID
()
string
//back current sessionID
SessionRelease
()
// release the resource
Flush
()
error
//delete all data
}
type
Provider
interface
{
SessionInit
(
maxlifetime
int64
,
savePath
string
)
error
SessionRead
(
sid
string
)
(
SessionStore
,
error
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
SessionStore
,
error
)
SessionDestroy
(
sid
string
)
error
SessionGC
()
}
...
...
@@ -44,40 +50,91 @@ type Manager struct {
cookieName
string
//private cookiename
provider
Provider
maxlifetime
int64
hashfunc
string
//support md5 & sha1
hashkey
string
options
[]
interface
{}
}
//options
//1. is https default false
//2. hashfunc default sha1
//3. hashkey default beegosessionkey
//4. maxage default is none
func
NewManager
(
provideName
,
cookieName
string
,
maxlifetime
int64
,
savePath
string
,
options
...
interface
{})
(
*
Manager
,
error
)
{
provider
,
ok
:=
provides
[
provideName
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"session: unknown provide %q (forgotten import?)"
,
provideName
)
}
provider
.
SessionInit
(
maxlifetime
,
savePath
)
return
&
Manager
{
provider
:
provider
,
cookieName
:
cookieName
,
maxlifetime
:
maxlifetime
,
options
:
options
},
nil
hashfunc
:=
"sha1"
if
len
(
options
)
>
1
{
hashfunc
=
options
[
1
]
.
(
string
)
}
hashkey
:=
"beegosessionkey"
if
len
(
options
)
>
2
{
hashkey
=
options
[
2
]
.
(
string
)
}
return
&
Manager
{
provider
:
provider
,
cookieName
:
cookieName
,
maxlifetime
:
maxlifetime
,
hashfunc
:
hashfunc
,
hashkey
:
hashkey
,
options
:
options
,
},
nil
}
//get Session
func
(
manager
*
Manager
)
SessionStart
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
session
SessionStore
)
{
cookie
,
err
:=
r
.
Cookie
(
manager
.
cookieName
)
maxage
:=
-
1
if
len
(
manager
.
options
)
>
3
{
switch
manager
.
options
[
3
]
.
(
type
)
{
case
int
:
if
manager
.
options
[
3
]
.
(
int
)
>
0
{
maxage
=
manager
.
options
[
3
]
.
(
int
)
}
else
if
manager
.
options
[
3
]
.
(
int
)
<
0
{
maxage
=
0
}
case
int64
:
if
manager
.
options
[
3
]
.
(
int64
)
>
0
{
maxage
=
int
(
manager
.
options
[
3
]
.
(
int64
))
}
else
if
manager
.
options
[
3
]
.
(
int64
)
<
0
{
maxage
=
0
}
case
int32
:
if
manager
.
options
[
3
]
.
(
int32
)
>
0
{
maxage
=
int
(
manager
.
options
[
3
]
.
(
int32
))
}
else
if
manager
.
options
[
3
]
.
(
int32
)
<
0
{
maxage
=
0
}
}
}
if
err
!=
nil
||
cookie
.
Value
==
""
{
sid
:=
manager
.
sessionId
()
sid
:=
manager
.
sessionId
(
r
)
session
,
_
=
manager
.
provider
.
SessionRead
(
sid
)
secure
:=
false
if
len
(
manager
.
options
)
>
0
{
secure
=
manager
.
options
[
0
]
.
(
bool
)
}
cookie
:=
http
.
Cookie
{
Name
:
manager
.
cookieName
,
cookie
=
&
http
.
Cookie
{
Name
:
manager
.
cookieName
,
Value
:
url
.
QueryEscape
(
sid
),
Path
:
"/"
,
HttpOnly
:
true
,
Secure
:
secure
}
if
maxage
>=
0
{
cookie
.
MaxAge
=
maxage
}
//cookie.Expires = time.Now().Add(time.Duration(manager.maxlifetime) * time.Second)
http
.
SetCookie
(
w
,
&
cookie
)
r
.
AddCookie
(
&
cookie
)
http
.
SetCookie
(
w
,
cookie
)
r
.
AddCookie
(
cookie
)
}
else
{
//cookie.Expires = time.Now().Add(time.Duration(manager.maxlifetime) * time.Second)
cookie
.
HttpOnly
=
true
cookie
.
Path
=
"/"
if
maxage
>=
0
{
cookie
.
MaxAge
=
maxage
}
http
.
SetCookie
(
w
,
cookie
)
sid
,
_
:=
url
.
QueryUnescape
(
cookie
.
Value
)
session
,
_
=
manager
.
provider
.
SessionRead
(
sid
)
...
...
@@ -103,10 +160,81 @@ func (manager *Manager) GC() {
time
.
AfterFunc
(
time
.
Duration
(
manager
.
maxlifetime
)
*
time
.
Second
,
func
()
{
manager
.
GC
()
})
}
func
(
manager
*
Manager
)
sessionId
()
string
{
func
(
manager
*
Manager
)
SessionRegenerateId
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
session
SessionStore
)
{
sid
:=
manager
.
sessionId
(
r
)
cookie
,
err
:=
r
.
Cookie
(
manager
.
cookieName
)
if
err
!=
nil
&&
cookie
.
Value
==
""
{
//delete old cookie
session
,
_
=
manager
.
provider
.
SessionRead
(
sid
)
secure
:=
false
if
len
(
manager
.
options
)
>
0
{
secure
=
manager
.
options
[
0
]
.
(
bool
)
}
cookie
=
&
http
.
Cookie
{
Name
:
manager
.
cookieName
,
Value
:
url
.
QueryEscape
(
sid
),
Path
:
"/"
,
HttpOnly
:
true
,
Secure
:
secure
,
}
}
else
{
oldsid
,
_
:=
url
.
QueryUnescape
(
cookie
.
Value
)
session
,
_
=
manager
.
provider
.
SessionRegenerate
(
oldsid
,
sid
)
cookie
.
Value
=
url
.
QueryEscape
(
sid
)
cookie
.
HttpOnly
=
true
cookie
.
Path
=
"/"
}
maxage
:=
-
1
if
len
(
manager
.
options
)
>
3
{
switch
manager
.
options
[
3
]
.
(
type
)
{
case
int
:
if
manager
.
options
[
3
]
.
(
int
)
>
0
{
maxage
=
manager
.
options
[
3
]
.
(
int
)
}
else
if
manager
.
options
[
3
]
.
(
int
)
<
0
{
maxage
=
0
}
case
int64
:
if
manager
.
options
[
3
]
.
(
int64
)
>
0
{
maxage
=
int
(
manager
.
options
[
3
]
.
(
int64
))
}
else
if
manager
.
options
[
3
]
.
(
int64
)
<
0
{
maxage
=
0
}
case
int32
:
if
manager
.
options
[
3
]
.
(
int32
)
>
0
{
maxage
=
int
(
manager
.
options
[
3
]
.
(
int32
))
}
else
if
manager
.
options
[
3
]
.
(
int32
)
<
0
{
maxage
=
0
}
}
}
if
maxage
>=
0
{
cookie
.
MaxAge
=
maxage
}
http
.
SetCookie
(
w
,
cookie
)
r
.
AddCookie
(
cookie
)
return
}
//remote_addr cruunixnano randdata
func
(
manager
*
Manager
)
sessionId
(
r
*
http
.
Request
)
(
sid
string
)
{
b
:=
make
([]
byte
,
24
)
if
_
,
err
:=
io
.
ReadFull
(
rand
.
Reader
,
b
);
err
!=
nil
{
return
""
}
return
base64
.
URLEncoding
.
EncodeToString
(
b
)
bs
:=
base64
.
URLEncoding
.
EncodeToString
(
b
)
sig
:=
fmt
.
Sprintf
(
"%s%d%s"
,
r
.
RemoteAddr
,
time
.
Now
()
.
UnixNano
(),
bs
)
if
manager
.
hashfunc
==
"md5"
{
h
:=
md5
.
New
()
h
.
Write
([]
byte
(
bs
))
sid
=
fmt
.
Sprintf
(
"%s"
,
hex
.
EncodeToString
(
h
.
Sum
(
nil
)))
}
else
if
manager
.
hashfunc
==
"sha1"
{
h
:=
hmac
.
New
(
sha1
.
New
,
[]
byte
(
manager
.
hashkey
))
fmt
.
Fprintf
(
h
,
"%s"
,
sig
)
sid
=
fmt
.
Sprintf
(
"%s"
,
hex
.
EncodeToString
(
h
.
Sum
(
nil
)))
}
else
{
h
:=
hmac
.
New
(
sha1
.
New
,
[]
byte
(
manager
.
hashkey
))
fmt
.
Fprintf
(
h
,
"%s"
,
sig
)
sid
=
fmt
.
Sprintf
(
"%s"
,
hex
.
EncodeToString
(
h
.
Sum
(
nil
)))
}
return
}
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment