Пример #1
0
// Save implements wcg.SessionStore#Save
func (s *SessionStore) Save(sess *wcg.Session) error {
	encoded, err := sess.Encode()
	if err != nil {
		return err
	}
	item := &EncodedSession{
		[]byte(encoded),
	}
	key := datastore.NewKey(s.ctx, "EncodedSession", string(sess.ID), 0, nil)
	_, err = datastore.Put(s.ctx, key, item)
	return err
}
Пример #2
0
// FindOAuth2UserInSession returns an OAuth2User object in the given session `s`.
func FindOAuth2UserInSession(s *wcg.Session, host string) *OAuth2User {
	if s == nil {
		return nil
	}
	key := fmt.Sprintf("oauth2://%s", host)
	d, ok := s.GetData(key)
	if !ok {
		return nil
	}
	user := &OAuth2User{Token: &oauth2.Token{}}
	values := make([]string, len(textfields))
	for i, v := range textfields {
		if values[i], ok = d.Get(v); !ok {
			s.Delete(key)
			return nil
		}
	}
	user.AccessToken = values[0]
	user.RefreshToken = values[1]
	user.id = values[2]
	user.displayName = values[3]
	user.profileLink = values[4]
	user.imageLink = values[5]
	user.authProvider = values[6]

	if user.Token.Expiry, ok = d.GetTime("expiry"); !ok {
		s.Delete(key)
		return nil
	}

	if user.lastLogin, ok = d.GetTime("last_login"); !ok {
		s.Delete(key)
		return nil
	}

	// Check if the token is expired or not.
	if user.Expired() {
		s.Delete(key)
		return nil
	}
	return user
}
Пример #3
0
// SessionSupportWithConfig returns two middleware functions for session support, which need to be registered
// on route.Before and route.After.
//
// Example:
//
//     sprepare, scomplete := SessionSupport()
//
//     route.Before(sprepare)
//     route.After(scomplete)
//
func SessionSupportWithConfig(cfg *SessionConfig) (wcg.Handler, wcg.Handler) {
	if cfg.StoreFactory == nil {
		memorystore := wcg.NewMemorySessionStore()
		cfg.StoreFactory = func(req *wcg.Request) wcg.SessionStore {
			req.Logger.Warnf("Memory SessionStore is used so that the session data would lost suddenly.")
			req.Logger.Warnf("If you are in GAE environment (including devserver), you must use GAESessionStoreFactory")
			return memorystore
		}
	}

	// load handler loads the session data from backend storage.
	load := func(res *wcg.Response, req *wcg.Request) {
		if res.IsClosed() {
			return
		}
		var sess *wcg.Session
		var err error
		store := cfg.StoreFactory(req)
		c, err := req.SignedCookie(cfg.CookieName, cfg.Key)
		if err != nil {
			req.Logger.Debugf("Could not decode the signed cookie on %s: %v", cfg.Key, err)
		}
		if c != nil {
			if wcg.IsUUID(c.Value) {
				sess, err = store.Load(wcg.UUID(c.Value))
			}
			if err != nil {
				req.Logger.Warnf(
					"Could not load the session (id: %q) from the store (%v), use a new session.",
					err, c.Value)
				sess = nil
				c = nil
			} else {
				if sess == nil {
					req.Logger.Debugf("Session data for %q was not found on backend.", c.Value)
				} else {
					req.Logger.Debugf("Session data for %q found.", c.Value)
					expiredAt := sess.Timestamp.Add(time.Duration(cfg.MaxAge) * time.Second)
					if expiredAt.Before(time.Now()) {
						// expired
						req.Logger.Infof("Session data for %q is found but expired.", c.Value)
						if _, err := store.Delete(sess.ID); err != nil {
							req.Logger.Errorf("An error occurred while deleting the expired session (%q): %v", sess.ID, err)
						}
						sess = nil
					}
				}
			}
		}
		if c == nil {
			// no cookie found
			c = &http.Cookie{}
			c.Name = cfg.CookieName
			c.HttpOnly = cfg.HTTPOnly
			c.MaxAge = cfg.MaxAge
			if cfg.Domain != "" {
				c.Domain = cfg.Domain
			}
		}

		c.Path = cfg.Path

		// No session found
		if sess == nil {
			sess = wcg.NewSession(req)
			sess.Timestamp = time.Now()
			req.Logger.Debugf("Creating the new session.")
			store := cfg.StoreFactory(req)
			err := store.Save(sess)
			if err != nil {
				res.RenderInternalError("New Session could not be created: %v", err)
				return
			}
		} else {
			// Update the timestamp.
			sess.Timestamp = time.Now()
		}

		// Set the cookie data
		c.Value = string(sess.ID)
		c.Expires = sess.Timestamp.Add(time.Duration(cfg.MaxAge) * time.Second)
		c.MaxAge = cfg.MaxAge
		req.Session = sess
		encoded, _ := sess.Encode()
		req.SetLocal("__session_support", encoded)
		res.SetSignedCookie(c, cfg.Key)
	}

	// save handler store the cookie data into backend storage.
	save := func(res *wcg.Response, req *wcg.Request) {
		if encoded, ok := req.Local("__session_support").(string); ok {
			nencoded, _ := req.Session.Encode()
			// Store session if it is changed.
			if encoded != nencoded {
				store := cfg.StoreFactory(req)
				err := store.Save(req.Session)
				if err != nil {
					// TODO: log session error
					req.Logger.Errorf("Could not save the session data on backend: %v", err)
				} else {
					req.Logger.Debugf("Successfully stored the session data on backend.")
				}
			} else {
				req.Logger.Debugf("Session is not changed, skipped to be stored.")
			}
		}
	}
	return wcg.NewNamedHandler("Session.Load", load), wcg.NewNamedHandler("Session.Save", save)
}