0

I will use Go to build a Web server. Now I want to have a session id returned to a user login with username and password. And I think I am ok with the login procedure. the user will use session id each time he wants to post data. However, after the user login, if the user does not send data within 3 minutes, I will try to destroy the session that makes the the session id no longer valid.

so how can I make the session expired when the user NOT post data within 3 minutes. ( I will use beego, beego have timeout for session but it does mention it will timeout depends on the post data interval )

Thanks.

Peter Hon
  • 321
  • 2
  • 6
  • 10
  • 1
    Post your current session code. Without knowing anything though, I would just set a 3 minute session expiry and refresh it on each request - a user who makes no requests in 3 minutes ends up with a stale session. – elithrar Aug 12 '14 at 09:37
  • 1
    PS: That would also be very frustrating, so I don't recommend doing that. – elithrar Aug 12 '14 at 09:37
  • 1
    Peter, If you're going to double-post all your questions between here and the Go mailing list, it's only polite to reference the SO questions so people aren't wasting their time. – JimB Aug 12 '14 at 14:10

1 Answers1

0

You could set the last time a session was used.

Suppose the cookie store is created as

Store := sessions.NewCookieStore("some-32-bit-long-secret")

You can then store the current time into the session:

// SetTime resets the activity time to the current time
func SetTime(w http.ResponseWriter, r *http.Request) error {
    ssn, err := Store.Get(r, cookieKey)
    if err != nil {
        return err
    }

    b, err := json.Marshal(time.Now())
    if err != nil {
        return err
    }

    ssn.Values[timeKey] = b
    return ssn.Save(r, w)
}

The last time of activity can then be found in the session:

// GetTime retrieves the last activity time from the session
func GetTime(ssn *sessions.Session) (*time.Time, error) {
    v := ssn.Values[timeKey]
    tm := &time.Time{}
    if b, ok := v.([]byte); ok {
        err := json.Unmarshal(b, tm)
        if err == nil {
            return tm, nil
        }
        return nil, err
    }

    return nil, errors.New("Time missing")
}

Next use a middleware function to test if the session should become invalid; if not then reset the activity time:

func (cfg *Config) Timer(next http.HandlerFunc, d time.Duration) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        ssn, err := cfg.Store.Get(r, cookieKey)
        if err != nil {
            http.Error(w, "Internal Server Error", http.StatusInternalServerError)
            return
        }

        if tm, err := GetTime(ssn); err == nil {
            if time.Since(*tm) > d {
                // invalidate user account in some way; it is assumed that the user 
                // info is stored in the session with the key value "userKey"
                session.Values[userKey] = ""
                session.Save(r, w) // should test for error
                // do something for a signed off user, e.g.:
                SignIn(w, r)
                return
            }

            if err = SetTime(w, r); err == nil {
                next(w, r)
                return
            }
        }

        http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
    }
}

The middleware can be used in the routing:

    ...
    r := mux.NewRouter()
    ...
    r.HandleFunc("/path", Timer(SomeHFunc, 3*time.Minute))
    ...
FrankS
  • 1