delete session
This commit is contained in:
@ -7,9 +7,11 @@ services:
|
|||||||
install:
|
install:
|
||||||
- export PATH=$PATH:$HOME/gopath/bin
|
- export PATH=$PATH:$HOME/gopath/bin
|
||||||
- go get -v github.com/leanote/leanote/app
|
- go get -v github.com/leanote/leanote/app
|
||||||
- go get github.com/revel/cmd/revel
|
- go get -u github.com/revel/cmd/revel
|
||||||
|
ls $GOPATH/github.com/revel/
|
||||||
|
# - go get github.com/revel/moudle/revel
|
||||||
# - go install github.com/revel/cmd/revel
|
# - go install github.com/revel/cmd/revel
|
||||||
- pwd
|
- pwd
|
||||||
- ls
|
- ls
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package session
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
"github.com/leanote/leanote/app/lea/memcache"
|
|
||||||
. "github.com/leanote/leanote/app/lea"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 使用filter
|
|
||||||
// 很巧妙就使用了memcache来处理session
|
|
||||||
// revel的session(cookie)只存sessionId, 其它信息存在memcache中
|
|
||||||
|
|
||||||
func MSessionFilter(c *revel.Controller, fc []revel.Filter) {
|
|
||||||
sessionId := c.Session.Id()
|
|
||||||
|
|
||||||
// 从memcache中得到cache, 赋给session
|
|
||||||
cache := revel.Session(memcache.GetMap(sessionId))
|
|
||||||
|
|
||||||
Log("memcache")
|
|
||||||
LogJ(cache)
|
|
||||||
if cache == nil {
|
|
||||||
cache = revel.Session{}
|
|
||||||
cache.Id()
|
|
||||||
}
|
|
||||||
c.Session = cache
|
|
||||||
|
|
||||||
// Make session vars available in templates as {{.session.xyz}}
|
|
||||||
c.RenderArgs["session"] = c.Session
|
|
||||||
|
|
||||||
fc[0](c, fc[1:])
|
|
||||||
|
|
||||||
// 再把session保存之
|
|
||||||
LogJ(c.Session)
|
|
||||||
memcache.SetMap(sessionId, c.Session, -1)
|
|
||||||
|
|
||||||
// 只留下sessionId
|
|
||||||
c.Session = revel.Session{revel.SESSION_ID_KEY: sessionId}
|
|
||||||
}
|
|
@ -1,208 +0,0 @@
|
|||||||
package session
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/revel/revel"
|
|
||||||
// . "github.com/leanote/leanote/app/lea"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 主要修改revel的cookie, 设置Domain
|
|
||||||
// 为了使sub domain共享cookie
|
|
||||||
// cookie.domain = leanote.com
|
|
||||||
|
|
||||||
// A signed cookie (and thus limited to 4kb in size).
|
|
||||||
// Restriction: Keys may not have a colon in them.
|
|
||||||
type Session map[string]string
|
|
||||||
|
|
||||||
const (
|
|
||||||
SESSION_ID_KEY = "_ID"
|
|
||||||
TIMESTAMP_KEY = "_TS"
|
|
||||||
)
|
|
||||||
|
|
||||||
// expireAfterDuration is the time to live, in seconds, of a session cookie.
|
|
||||||
// It may be specified in config as "session.expires". Values greater than 0
|
|
||||||
// set a persistent cookie with a time to live as specified, and the value 0
|
|
||||||
// sets a session cookie.
|
|
||||||
var expireAfterDuration time.Duration
|
|
||||||
var cookieDomain = "" // life
|
|
||||||
func init() {
|
|
||||||
// Set expireAfterDuration, default to 30 days if no value in config
|
|
||||||
revel.OnAppStart(func() {
|
|
||||||
var err error
|
|
||||||
if expiresString, ok := revel.Config.String("session.expires"); !ok {
|
|
||||||
expireAfterDuration = 30 * 24 * time.Hour
|
|
||||||
} else if expiresString == "session" {
|
|
||||||
expireAfterDuration = 0
|
|
||||||
} else if expireAfterDuration, err = time.ParseDuration(expiresString); err != nil {
|
|
||||||
panic(fmt.Errorf("session.expires invalid: %s", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
cookieDomain, _ = revel.Config.String("cookie.domain")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Id retrieves from the cookie or creates a time-based UUID identifying this
|
|
||||||
// session.
|
|
||||||
func (s Session) Id() string {
|
|
||||||
if sessionIdStr, ok := s[SESSION_ID_KEY]; ok {
|
|
||||||
return sessionIdStr
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]byte, 32)
|
|
||||||
if _, err := rand.Read(buffer); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s[SESSION_ID_KEY] = hex.EncodeToString(buffer)
|
|
||||||
return s[SESSION_ID_KEY]
|
|
||||||
}
|
|
||||||
|
|
||||||
// getExpiration return a time.Time with the session's expiration date.
|
|
||||||
// If previous session has set to "session", remain it
|
|
||||||
func (s Session) getExpiration() time.Time {
|
|
||||||
if expireAfterDuration == 0 || s[TIMESTAMP_KEY] == "session" {
|
|
||||||
// Expire after closing browser
|
|
||||||
return time.Time{}
|
|
||||||
}
|
|
||||||
return time.Now().Add(expireAfterDuration)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cookie returns an http.Cookie containing the signed session.
|
|
||||||
func (s Session) cookie() *http.Cookie {
|
|
||||||
var sessionValue string
|
|
||||||
ts := s.getExpiration()
|
|
||||||
s[TIMESTAMP_KEY] = getSessionExpirationCookie(ts)
|
|
||||||
for key, value := range s {
|
|
||||||
if strings.ContainsAny(key, ":\x00") {
|
|
||||||
panic("Session keys may not have colons or null bytes")
|
|
||||||
}
|
|
||||||
if strings.Contains(value, "\x00") {
|
|
||||||
panic("Session values may not have null bytes")
|
|
||||||
}
|
|
||||||
sessionValue += "\x00" + key + ":" + value + "\x00"
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionData := url.QueryEscape(sessionValue)
|
|
||||||
cookie := http.Cookie{
|
|
||||||
Name: revel.CookiePrefix + "_SESSION",
|
|
||||||
Value: revel.Sign(sessionData) + "-" + sessionData,
|
|
||||||
Path: "/",
|
|
||||||
HttpOnly: revel.CookieHttpOnly,
|
|
||||||
Secure: revel.CookieSecure,
|
|
||||||
Expires: ts.UTC(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if cookieDomain != "" {
|
|
||||||
cookie.Domain = cookieDomain
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cookie
|
|
||||||
}
|
|
||||||
|
|
||||||
// sessionTimeoutExpiredOrMissing returns a boolean of whether the session
|
|
||||||
// cookie is either not present or present but beyond its time to live; i.e.,
|
|
||||||
// whether there is not a valid session.
|
|
||||||
func sessionTimeoutExpiredOrMissing(session Session) bool {
|
|
||||||
if exp, present := session[TIMESTAMP_KEY]; !present {
|
|
||||||
return true
|
|
||||||
} else if exp == "session" {
|
|
||||||
return false
|
|
||||||
} else if expInt, _ := strconv.Atoi(exp); int64(expInt) < time.Now().Unix() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSessionFromCookie returns a Session struct pulled from the signed
|
|
||||||
// session cookie.
|
|
||||||
func getSessionFromCookie(cookie *http.Cookie) Session {
|
|
||||||
session := make(Session)
|
|
||||||
|
|
||||||
// Separate the data from the signature.
|
|
||||||
hyphen := strings.Index(cookie.Value, "-")
|
|
||||||
if hyphen == -1 || hyphen >= len(cookie.Value)-1 {
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
sig, data := cookie.Value[:hyphen], cookie.Value[hyphen+1:]
|
|
||||||
|
|
||||||
// Verify the signature.
|
|
||||||
if !revel.Verify(data, sig) {
|
|
||||||
revel.INFO.Println("Session cookie signature failed")
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
|
|
||||||
revel.ParseKeyValueCookie(data, func(key, val string) {
|
|
||||||
session[key] = val
|
|
||||||
})
|
|
||||||
|
|
||||||
if sessionTimeoutExpiredOrMissing(session) {
|
|
||||||
session = make(Session)
|
|
||||||
}
|
|
||||||
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionFilter is a Revel Filter that retrieves and sets the session cookie.
|
|
||||||
// Within Revel, it is available as a Session attribute on Controller instances.
|
|
||||||
// The name of the Session cookie is set as CookiePrefix + "_SESSION".
|
|
||||||
func SessionFilter(c *revel.Controller, fc []revel.Filter) {
|
|
||||||
session := restoreSession(c.Request.Request)
|
|
||||||
// c.Session, 重新生成一个revel.Session给controller!!!
|
|
||||||
// Log("sessoin--------")
|
|
||||||
// LogJ(session)
|
|
||||||
revelSession := revel.Session(session) // 强制转换 还是同一个对象, 但有个问题, 这样Session.Id()方法是用revel的了
|
|
||||||
c.Session = revelSession
|
|
||||||
// 生成sessionId
|
|
||||||
c.Session.Id()
|
|
||||||
sessionWasEmpty := len(c.Session) == 0
|
|
||||||
|
|
||||||
// Make session vars available in templates as {{.session.xyz}}
|
|
||||||
c.RenderArgs["session"] = c.Session
|
|
||||||
|
|
||||||
fc[0](c, fc[1:])
|
|
||||||
|
|
||||||
// Store the signed session if it could have changed.
|
|
||||||
if len(c.Session) > 0 || !sessionWasEmpty {
|
|
||||||
// 转换成lea.Session
|
|
||||||
session = Session(c.Session)
|
|
||||||
c.SetCookie(session.cookie())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// restoreSession returns either the current session, retrieved from the
|
|
||||||
// session cookie, or a new session.
|
|
||||||
func restoreSession(req *http.Request) Session {
|
|
||||||
cookie, err := req.Cookie(revel.CookiePrefix + "_SESSION")
|
|
||||||
if err != nil {
|
|
||||||
return make(Session)
|
|
||||||
} else {
|
|
||||||
return getSessionFromCookie(cookie)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSessionExpirationCookie retrieves the cookie's time to live as a
|
|
||||||
// string of either the number of seconds, for a persistent cookie, or
|
|
||||||
// "session".
|
|
||||||
func getSessionExpirationCookie(t time.Time) string {
|
|
||||||
if t.IsZero() {
|
|
||||||
return "session"
|
|
||||||
}
|
|
||||||
return strconv.FormatInt(t.Unix(), 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNoExpiration sets session to expire when browser session ends
|
|
||||||
func (s Session) SetNoExpiration() {
|
|
||||||
s[TIMESTAMP_KEY] = "session"
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDefaultExpiration sets session to expire after default duration
|
|
||||||
func (s Session) SetDefaultExpiration() {
|
|
||||||
delete(s, TIMESTAMP_KEY)
|
|
||||||
}
|
|
Reference in New Issue
Block a user