Sessions: ์ฝ”๋ฑ์— ์˜ต์…˜์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ ์šฉํ•˜์ง€ ์•Š๋Š” ํƒ€์‚ฌ ์ €์žฅ์†Œ.

์— ๋งŒ๋“  2015๋…„ 07์›” 10์ผ  ยท  17์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: gorilla/sessions

์ด ํŒจํ‚ค์ง€๋ฅผ ๋ฐฉ๊ธˆ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ๋Š”๋ฐ ์ฟ ํ‚ค๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜ base64 ์ธ์ฝ”๋”ฉ ์ฟ ํ‚ค ๋ฐ์ดํ„ฐ ๋Œ€์‹  _ga = GA1.1.922831813.14264788986๊ณผ ๊ฐ™์€ ํ•ญ๋ชฉ์„ ์„ค์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ๋˜๋Š” ์–ธ์ œ ๊ณ ์žฅ ๋‚ฌ๋Š”์ง€ ์•Œ๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜๋Š” ๋ฒ„์ „์œผ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌ!

bug stale

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด๋Š” ๋˜ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์Šคํ† ์–ด ๊ตฌํ˜„์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. ๋ชจ๋‘ ๋ฐฑ์—”๋“œ ์Šคํ† ์–ด์— ID๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋ณด์•ˆ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

redistore ์€ ์ˆ˜๋™์œผ๋กœ SetMaxAge ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ ์˜ฌ๋ฐ”๋ฅธ ๊ตฌํ˜„์˜ ์ ˆ๋ฐ˜์ด์ง€๋งŒ ๊ธฐ๋ณธ ์‚ฌ๋ก€์— ์ง์ ‘ ์ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ (30 ์ผ)์€ ๋ณด์•ˆ ์ฟ ํ‚ค์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๊ฐ„๋žตํžˆ ์‚ดํŽด๋ณด๋ฉด _all_ ๋‹ค๋ฅธ ์ƒ์ ์ด ์˜ํ–ฅ์„๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. Options ๊ตฌ์กฐ์ฒด๋ฅผ ํ†ตํ•œ MaxAge ์„ค์ •์€ CodecsFromPairs์—์„œ ์ƒ์„ฑ ๋œ ๊ธฐ๋ณธ ๋ณด์•ˆ ์ฟ ํ‚ค ์ธ์Šคํ„ด์Šค์— ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž๋Š” ๋ณด์•ˆ ์ฟ ํ‚ค๊ฐ€ HMAC์— ์•”์‹œ ์ ์œผ๋กœ ํฌํ•จ ๋œ ๊ฒƒ๋ณด๋‹ค ๋งŒ๋ฃŒ ๋‚ ์งœ๋ฅผ _less_ ์„ค์ •ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์ตœ์ข… ์‚ฌ์šฉ์ž๋Š”์ด ๋ฒ„๊ทธ๋ฅผ ๊ฒช์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

FWIW : ๋˜ํ•œ "๋จผ ๋ฏธ๋ž˜"์ฟ ํ‚ค ๋งŒ๋ฃŒ๋Š” ํŠน๋ณ„ํžˆ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด ์ข‹์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  17 ๋Œ“๊ธ€

"_ga"์ฟ ํ‚ค๋Š” ๊ณ ๋ฆด๋ผ / ์„ธ์…˜๊ณผ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. Google Analytics์ž…๋‹ˆ๋‹ค.
์ฟ ํ‚ค.

๊ณ ๋ฆด๋ผ / ์„ธ์…˜์ด ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ (์ค‘๋‹จ๋˜์ง€ ์•Š์€
๋ณ€๊ฒฝ ์‚ฌํ•ญ) ๊ด€๋ จ ์ฝ”๋“œ์™€ ์ฟ ํ‚ค ์ฐฝ์˜ ์ถœ๋ ฅ์„ ๊ฒŒ์‹œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
๋ธŒ๋ผ์šฐ์ €์—์„œ? (๊ฒ€์‚ฌ๊ธฐ> ๋ฆฌ์†Œ์Šค> Chrome์˜ ์ฟ ํ‚ค)

2015 ๋…„ 7 ์›” 10 ์ผ ๊ธˆ์š”์ผ ์˜ค์ „ 7:12 marksalpeter [email protected]
์ผ๋‹ค:

์ด ํŒจํ‚ค์ง€๋ฅผ ๋ฐฉ๊ธˆ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ๋Š”๋ฐ ์ฟ ํ‚ค๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์˜
์ผ๋ฐ˜ ๋Œ€์‹  _ga = GA1.1.922831813.14264788986๊ณผ ๊ฐ™์€ ์„ค์ •
base64๋กœ ์ธ์ฝ”๋”ฉ ๋œ ์ฟ ํ‚ค ๋ฐ์ดํ„ฐ. ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ๋˜๋Š” ์ด๊ฒƒ์ด ์–ธ์ œ ๊ทธ๋ ‡๊ฒŒ ๊นจ ์กŒ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ž‘๋™ํ•˜๋Š” ๋ฒ„์ „์œผ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌ!

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/gorilla/sessions/issues/48.

์•ˆ๋…•ํ•˜์„ธ์š” Matt,

Mark์™€ ํ•จ๊ป˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ์ค‘์ด๋ฉฐ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ์•Œ๋ ค ๋“œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์›๋ž˜ ๋ฌธ์ œ๋Š” MaxAge๋ฅผ ๋งค์šฐ ๋งŽ์€ ์ˆ˜๋กœ ์„ค์ •ํ•˜๋”๋ผ๋„ 30 ์ผ ํ›„์— ๋งŒ๋ฃŒ๋˜๋Š” ์ฟ ํ‚ค์— ๋Œ€ํ•œ ๋ฌธ์ œ ์˜€๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฉ๊ธˆ ํŒจํ‚ค์ง€๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ํ˜„์žฌ ์‚ฌ์šฉ ์ค‘์ด๋ฉฐ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ์ธ์ฆ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

const (
AUTH_SESSION_NAME = "์ธ์ฆ ์„ธ์…˜"
)

var (
config = jconfig.LoadConfig (global.CONFIG () + "securecookie.json")
authKey = [] byte (config.GetString ( "authorization_key"))
encryptionKey = [] byte (config.GetString ( "encryption_key"))
์„ธ์…˜ = sessions.NewCookieStore (authKey, encryptionKey)
)

func init () {

apiRouter.HandleFunc("/auth/"   , Authenticate      )
apiRouter.HandleFunc("/deauth/"  , Deauthenticate   )
apiRouter.HandleFunc("/reauth/" , ReAuthenticate    )

// register complex data types for saving in sessions
gob.Register(&models.Device{})
gob.Register(&models.Manager{})
gob.Register(&models.SalesRep{})

// modify the options of the session store so that the auth cookie never expires (this is set so it expires in 200 years...)
session.Options.MaxAge = 6307200000

}

//์ด ํ•ธ๋“ค๋Ÿฌ๋Š” ์žฅ์น˜ ๋ฐ ๊ด€๋ฆฌ์ž๋ฅผ ์œ„ํ•ด ์‹œ์Šคํ…œ์—์„œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.
// ์š”์ฒญ์ž๊ฐ€ ์ด๋ฏธ ์ธ์ฆ ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. defferent๋ฅผ ์ธ์ฆํ•˜๋ ค๋ฉด
// ๊ณ„์ •, ๋จผ์ € ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ฆ์„ ํ•ด์ œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
//
// ๋งค๊ฐœ ๋ณ€์ˆ˜
// ์‚ฌ์šฉ์ž:
//
// ์ฐธ๊ณ  :์ด ์ธ์ฆ ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ ๋œ ๋ฐ์ดํ„ฐ๋Š” ์ •ํ™•ํ•จ ๋งŒ ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.
// ์‚ฌ์šฉ์ž๊ฐ€ ์ฒ˜์Œ ์ธ์ฆ ํ•  ๋•Œ. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์„ธ์…˜์— ์บ์‹œ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
//
func Authenticate (response http.ResponseWriter, request * http.Request) {

log.Println("Authenticate")

// open the session
auth_session, err :=  session.Get(request, AUTH_SESSION_NAME)
if err != nil {
    log.Println("there was an error retreiving the session:", err)
    InternalServerError(response, request)
    return
}

// already authroized as a manager
if manager, ok := auth_session.Values["manager"].(*models.Manager); ok {
    log.Printf("already logged in as manager %d", manager.Id)
    Success(response, request, manager)

// already authrorized as a device
} else if device, ok := auth_session.Values["device"].(*models.Device); ok {
    log.Printf("already logged in as device %d", device.Id)
    Success(response, request, device)

// attempt to gain authroization
} else {            
    fp  := parsers.FormParser(request)  

    // login as a manager
    if username, password := fp.GetString("user", ""), fp.GetString("pass", ""); username != "" && password != ""  {

        db := database.Open()
        defer db.Close()


        if manager := db.LoginAsManager(username, password); manager != nil {
            auth_session.Values["manager"] = manager

            // manager session error
            if err := auth_session.Save(request, response); err != nil {
                log.Printf("manager could not save session %s !\n", err.Error())
                InternalServerError(response, request)

            // manager login in success
            } else {
                log.Printf("logged in as manager %d !\n", manager.Id)
                Success(response, request, manager)     
            }

        // manager login failed
        } else {
            log.Printf("manager credentials not valid!")
            Unauthroized(response, request)
        }

    // login as a salesrep
    } else if username, password := fp.GetString("username", ""), fp.GetString("password", ""); username != "" && password != "" {

        db := database.Open()
        defer db.Close()


        if sales_rep_id := db.LoginAsSalesRep(username, password); sales_rep_id > 0 {

            sales_reps := db.GetSalesRep(&models.SalesRep{ Id: sales_rep_id });

            auth_session.Values["sales_rep"] = sales_reps[0];

            // sales rep session error
            if err := auth_session.Save(request, response); err != nil {
                log.Printf("sales rep could not save session %s !\n", err.Error())
                InternalServerError(response, request)

            // sales rep login in success
            } else {
                log.Printf("logged in as sales rep %d !\n", manager.Id)
                Success(response, request, manager)     
            }

        // sales rep login failed
        } else {
            log.Printf("sales rep credentials not valid!")
            Unauthroized(response, request)
        }

    // login as a device
    } else if pin_code := fp.GetInt32("PinCode", -1); pin_code > 0 {

        db := database.Open()
        defer db.Close()

        if devices := db.GetDevice(&models.Device{ PinCode:pin_code }, nil); len(devices) > 0 {
            auth_session.Values["device"] = &devices[0]

            // device session error
            if err := auth_session.Save(request, response); err != nil {
                log.Printf("device could not save session %s !\n", err.Error())
                InternalServerError(response, request)

            // device login in success
            } else {
                log.Printf("logged in as device %d !\n", devices[0].Id)
                Success(response, request, devices[0])      
            }

        // device login failed
        } else {
            log.Printf("device credentials not valid!")
            Unauthroized(response, request)
        }


    // no valid credentials were provided   
    } else {
        log.Println("no valid deivce or manager credentials")
        BadRequest(response, request)
    }

}

}

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ 30 ์ผ ํ›„์— ๋กœ๊ทธ์—์„œ ์–ป๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์žฅ์น˜ ์ฟ ํ‚ค : authentication-session = _KaJDVq4lIdQgeHiHcnSMw1IEPDyg3-9XEIBBPxw ==; ๊ฒฝ๋กœ = /; Expires = ์›”์š”์ผ, 2215 ๋…„ 5 ์›” 15 ์ผ 20:47:49 UTC; ์ตœ๋Œ€ ์—ฐ๋ น = 6307200000

2015/07/10 15:56:04 /routers/api/Auth.go:70 : securecookie : ๋งŒ๋ฃŒ ๋œ ํƒ€์ž„ ์Šคํƒฌํ”„

์ฟ ํ‚ค๋Š” MaxAge ์„ค์ •์— ๊ด€๊ณ„์—†์ด 30 ์ผ ํ›„์— ๋ชจ๋‘ ๋งŒ๋ฃŒ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์—๊ฒŒ ํฐ ๋„์›€์ด ๋˜์‹ญ์‹œ์˜ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ข‹์•„, ๋‚˜๋Š” ์ „์ฒด ์ƒ์ ์—์„œ MaxAge ๋ฅผ 2 ๊ฐœ์›” (86400 * 60)๋กœ ์„ค์ •ํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ๋ฐ๋ชจ ํ”„๋กœ๊ทธ๋žจ์„ ๋ชจ์˜ํ–ˆ๋‹ค.

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte("some-appropriately-auth-key"))

func SomeHandler(w http.ResponseWriter, r *http.Request) {
    session, err := store.Get(r, "example")
    if err != nil {
        http.Error(w, "No good!", 500)
        return
    }

    session.Values["gorilla"] = "sessions!"
    err = session.Save(r, w)
    if err != nil {
        http.Error(w, "No good!", 500)
        return
    }

    fmt.Fprintf(w, "%v", session.Values["gorilla"])
}

func main() {
    store.Options = &sessions.Options{
        MaxAge: 86400 * 60, // 2 months
    }

    http.HandleFunc("/", SomeHandler)
    log.Fatal(http.ListenAndServe(":8002", nil))
}

์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ์˜ˆ์ƒํ–ˆ๋˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Expiry time test

์‚ผ์‹ญ์‚ผ์ผ๋„ ๋‚˜์—๊ฒŒ ๊ทธ๋ฌผ ~ ์ˆ˜๋™์œผ๋กœ ์•ž์œผ๋กœ ๋‚ด ์‹œ๊ณ„๋ฅผ ์„ค์ • expired timestamp ์—์„œ ์˜ค๋ฅ˜๋ฅผ securecookie ์˜ค๋ฅ˜๊ฐ€ -.

๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฟ ํ‚ค๋ฅผ ์ง€์šฐ๊ณ  ์‹œ๊ณ„๋ฅผ now ()๋กœ ๋‹ค์‹œ ์„ค์ • ํ•œ ๋‹ค์Œ ๋‹ค์Œ์„ ํ†ตํ•ด ๊ธฐ๋ณธ *securecookie.SecureCookie MaxAge ์„ ๊ฐ•์ œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    store.Options = &sessions.Options{
        MaxAge: 86400 * 60, // 2 months
    }
    for _, s := range store.Codecs {
        if cookie, ok := s.(*securecookie.SecureCookie); ok {
            cookie.MaxAge(86400 * 90)
        }
    }

๊ฐ ์ฝ”๋ฑ์˜ maxAge ํ•„๋“œ๊ฐ€ http.Cookie ์ž‘์„ฑํ•  ๋•Œ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œ์‹œ๋˜๋Š” ๋‚ด์šฉ์— ์˜ํ–ฅ์„์ฃผ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์•ž์œผ๋กœ +2 ๊ฐœ์›” ๋งŒ๋ฃŒ๋˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์ฟ ํ‚ค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹œ๊ณ„๋ฅผ +33 ์ผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋งŒ๋ฃŒ ๋œ ํƒ€์ž„ ์Šคํƒฌํ”„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ช‡ ๊ฐ€์ง€ ํŒŒ๊ณ  ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

  • https://github.com/gorilla/securecookie/blob/master/securecookie.go#L244 -L246์—์„œ "securecookie : ๋งŒ๋ฃŒ ๋œ ํƒ€์ž„ ์Šคํƒฌํ”„"์˜ค๋ฅ˜๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • ์ด ์ค„์€ CookieStore ์ƒ์„ฑ์‹œ MaxAge๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. https://github.com/gorilla/sessions/blob/master/store.go#L54 -L56
  • ์˜ต์…˜์„ ์ ์šฉํ•˜๊ธฐ ์ „์— CodecsFromPairs ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ฐ *securecookie.SecureCookie (์ฝ”๋ฑ ์Šฌ๋ผ์ด์Šค์˜ ์ผ๋ถ€) ๋‚ด s.MaxAge ๊ฐ€ securecookie์˜ ๊ธฐ๋ณธ๊ฐ’ ์ธ 86400 * 30 ๋ฉ๋‹ˆ๋‹ค.
  • ์œ„์˜ ์Šค ๋‹ˆํŽซ์— ๋”ฐ๋ผ sessions.CookieStore.Codecs ์ดˆ๊ณผํ•˜๊ณ  ๊ฐ ๋ณด์•ˆ ์ฟ ํ‚ค ์ธ์Šคํ„ด์Šค์— MaxAge๋ฅผ ์„ค์ •ํ•˜๋ฉด์ด๋ฅผ ์šฐํšŒํ•ฉ๋‹ˆ๋‹ค.

TL; DR : ๊ทผ๋ณธ ์›์ธ์€ ๋ธŒ๋ผ์šฐ์ €์— ์ž‘์„ฑ๋œ http.Cookie ๊ฐ€ ์˜ต์…˜์—์„œ ์„ค์ • ํ•œ ํƒ€์ž„ ์Šคํƒฌํ”„๋ฅผ ๊ฐ€์ ธ ์˜ค์ง€๋งŒ ๊ธฐ๋ณธ ๋ณด์•ˆ ์ฟ ํ‚ค ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ HMAC๋Š” date | value | mac-์—ฌ๊ธฐ์„œ date๋Š” ์˜ต์…˜์ด ์ˆ˜์ •ํ•˜์ง€ ์•Š๋Š” _default_ MaxAge. ์ดํ›„ 30 ์ผ ์ด์ƒ์ด๋˜๋ฉด HMAC ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ • ์‚ฌํ•ญ์€ sessions.NewCookieStore ๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋ฑ์— ๋Œ€ํ•ด ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๊ณ  Options.MaxAge๋ฅผ ๊ฐ *securecookie.SecureCookie ์ธ์Šคํ„ด์Šค์— ์ ์šฉํ•˜์—ฌ ์ฟ ํ‚ค ๋งŒ๋ฃŒ์™€ HMAC ํƒ€์ž„ ์Šคํƒฌํ”„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ฐ„์˜ ๋ถˆ์ผ์น˜๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋กํ•ฉ๋‹ˆ๋‹ค.

cc / @kisielk ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์ • ์‚ฌํ•ญ์„ ํ‘ธ์‹œํ•˜๊ธฐ ์ „์— ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ถ”์‹  : ์ด๊ฒƒ๊ณผ ๊ด€๊ณ„์—†์ด ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‹จ์ผ DB ํ’€์„ ์—ฌ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ „์—ญ์„ ํ†ตํ•˜๊ฑฐ๋‚˜ ํฌ์ธํ„ฐ๋ฅผ ๋ช…์‹œ ์ ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์š”์ฒญ๋ณ„๋กœ ํ’€์„ ์—ด๊ณ  ๋‹ซ์œผ๋ฉด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋ฉ๋‹ˆ๋‹ค. *sql.DB ์€ ๋™์‹œ ์•ก์„ธ์Šค์— ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๋˜ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์Šคํ† ์–ด ๊ตฌํ˜„์— ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. ๋ชจ๋‘ ๋ฐฑ์—”๋“œ ์Šคํ† ์–ด์— ID๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋ณด์•ˆ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

redistore ์€ ์ˆ˜๋™์œผ๋กœ SetMaxAge ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ ์˜ฌ๋ฐ”๋ฅธ ๊ตฌํ˜„์˜ ์ ˆ๋ฐ˜์ด์ง€๋งŒ ๊ธฐ๋ณธ ์‚ฌ๋ก€์— ์ง์ ‘ ์ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ (30 ์ผ)์€ ๋ณด์•ˆ ์ฟ ํ‚ค์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๊ฐ„๋žตํžˆ ์‚ดํŽด๋ณด๋ฉด _all_ ๋‹ค๋ฅธ ์ƒ์ ์ด ์˜ํ–ฅ์„๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. Options ๊ตฌ์กฐ์ฒด๋ฅผ ํ†ตํ•œ MaxAge ์„ค์ •์€ CodecsFromPairs์—์„œ ์ƒ์„ฑ ๋œ ๊ธฐ๋ณธ ๋ณด์•ˆ ์ฟ ํ‚ค ์ธ์Šคํ„ด์Šค์— ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž๋Š” ๋ณด์•ˆ ์ฟ ํ‚ค๊ฐ€ HMAC์— ์•”์‹œ ์ ์œผ๋กœ ํฌํ•จ ๋œ ๊ฒƒ๋ณด๋‹ค ๋งŒ๋ฃŒ ๋‚ ์งœ๋ฅผ _less_ ์„ค์ •ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฏ€๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์ตœ์ข… ์‚ฌ์šฉ์ž๋Š”์ด ๋ฒ„๊ทธ๋ฅผ ๊ฒช์ง€ ์•Š์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

FWIW : ๋˜ํ•œ "๋จผ ๋ฏธ๋ž˜"์ฟ ํ‚ค ๋งŒ๋ฃŒ๋Š” ํŠน๋ณ„ํžˆ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด ์ข‹์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ํ˜„์žฌ ๊ตฌํ˜„์—์„œ ํ˜„์žฌ ํƒ€์ž„ ์Šคํƒฌํ”„๊ฐ€ ์™„์ „ํžˆ ์•”ํ˜ธํ™”๋˜์ง€ ์•Š์•˜ ์Œ์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๋ก ์ ์œผ๋กœ๋Š” base64๋กœ ์ฟ ํ‚ค๋ฅผ ๋””์ฝ”๋”ฉํ•˜๊ณ  ํƒ€์ž„ ์Šคํƒฌํ”„๋ฅผ ํ˜„์žฌ ๋‚ ์งœ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  base64๋กœ ์ฟ ํ‚ค๋ฅผ ์ธ์ฝ”๋”ฉํ•˜๋ฉด options.MaxAge ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜๋”๋ผ๋„ MaxAge ์†์„ฑ์€ ์ „ํ˜€ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋„ค, "๋จผ ๋ฏธ๋ž˜"์ฟ ํ‚ค๋Š” ๋‹จ์ง€ ํ…Œ์ŠคํŠธ ์šฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์—์„œ MaxAge๋ฅผ 0์œผ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฃผ๋ง ๋™์•ˆ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ๋น„์Šทํ•œ ์ˆ˜์ •์„ ์ž‘์„ฑํ–ˆ์ง€๋งŒ ๊ท€ํ•˜์˜ ๊ฒƒ๋ณด๋‹ค ์•ฝ๊ฐ„ ๋œ ๊ฐ„๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ์กฐ์‚ฌํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@wbaron- ๋ฌธ์ œ ์—†์Šต๋‹ˆ๋‹ค. ๊ณง ์—…์ŠคํŠธ๋ฆผ ํŒจํ‚ค์ง€์—์„œ ์ˆ˜์ • ๋  ์˜ˆ์ •์ด๋ฉฐ
ํ•œ ๋ฒˆ ์™„๋ฃŒ๋˜๋ฉด ํ•‘์„ํ•˜์—ฌ ์ž์‹ ์˜ ํฌํฌ๋ฅผ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
์›ํ•˜์ง€ ์•Š์Œ).

@marksalpeter- ์–ด๋””๋ฅผ ์ง€์  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ณด์•ˆ ์ฟ ํ‚ค MAC
๋ฌธ์ž์—ด ํ‘œํ˜„์„ ์œ„ํ•ด base64๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ธฐ ์ „์˜ name | date | value. ๋งŒ์•ฝ
ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋””์ฝ”๋”ฉํ•˜๋ฉด ํƒ€์ž„ ์Šคํƒฌํ”„๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
MAC'edโ€” ์‹ค์ œ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.)
MAC์ด ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฟ ํ‚ค๋Š” ๋””์ฝ”๋”ฉ (์š”์ฒญ)์—์„œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
ํ•ด์‹œ / ์ธ์ฆ ํ‚ค์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋””์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ  :
https://github.com/gorilla/securecookie/blob/master/securecookie.go#L185 -L191

2015 ๋…„ 7 ์›” 14 ์ผ ํ™”์š”์ผ ์˜คํ›„ 10:40 wbaron [email protected] ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

๋„ค, "๋จผ ๋ฏธ๋ž˜"์ฟ ํ‚ค๋Š” ํ…Œ์ŠคํŠธ ์šฉ์ด์—ˆ๊ณ  MaxAge๋Š”
์ด์ œ ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์—์„œ 0์ž…๋‹ˆ๋‹ค. ์ฃผ๋ง ๋™์•ˆ ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๊ณ 
์•ฝ๊ฐ„ ๋œ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋‹น์‹ ๊ณผ ๋น„์Šทํ•œ ์ˆ˜์ •์„ ์ผ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ์กฐ์‚ฌํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/gorilla/sessions/issues/48#issuecomment -121257995.

@elithrar ๋‚ด ์‹ค์ˆ˜. ์ฟ ํ‚ค๋ฅผ ๋””์ฝ”๋”ฉ ํ•  ๋•Œ [ํƒ€์ž„ ์Šคํƒฌํ”„] | [MAC ์ •๋ณด]๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ์ตœ๋Œ€ ์ •๋ณด ์ด์ „์˜ ํƒ€์ž„ ์Šคํƒฌํ”„๊ฐ€ ์‚ฌ์šฉ์ค‘์ธ ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

@elithrar ๋‹น์‹ ์ด ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์ข‹์€ ์†Œ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ๋งค์žฅ์— ๊ฐœ๋ณ„์ ์œผ๋กœ ์ ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ์ ์ด ์•„์‰ฝ์Šต๋‹ˆ๋‹ค.

@kisielk- ๋ถ„๋ช…ํžˆ ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. ์ œ 3์ž๋ฅผ ๋งŒ์ง€๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.
์ œ 3 ์ž ๋งค์žฅ์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ฒฐํ•ฉ ํ•  ์ˆ˜์žˆ๋Š” ๊นจ๋—ํ•œ ๋ฐฉ๋ฒ•์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
๋ณด์•ˆ ์ฟ ํ‚ค์—์„œ s.MaxAge ๋ฉ”์†Œ๋“œ๊ฐ€์žˆ๋Š” Options.MaxAge ํ•„๋“œ.

๋ณด์•ˆ ์ฟ ํ‚ค์—์„œ func CodecMaxAge(codecs []Codec, age int) []Codec ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค (๋‹จ์  :
์ธํ„ฐํŽ˜์ด์Šค + ๊ณต์šฉ API์— ์ถ”๊ฐ€) ๋‚ด๋ถ€์ ์œผ๋กœ ์œ ํ˜•์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
assertion + ๊ฐ ์ฝ”๋ฑ์—์„œ s.MaxAge (age)๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ค‘๋ณต์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค (๋ฃจํ”„
์Šฌ๋ผ์ด์Šค, ์ฟ ํ‚ค ์œ ํ˜•์— ์–ด์„ค ์…˜ ์ž…๋ ฅ) ํƒ€์‚ฌ ์ €์žฅ์†Œ์˜ ์ฝ”๋“œ
NewXXXXStore ํ•จ์ˆ˜์—์„œ securecookie.CodecMaxAge(mystore.Codecs, mystore.opts.MaxAge) ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ
๊ธฐ๋ณธ s.maxAge ํ•„๋“œ.

๋” ๋‚˜์€ ์•„์ด๋””์–ด์— ๊ฐœ๋ฐฉ์ ์ด์ง€๋งŒ ์ด๊ฒƒ์ด ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

2015 ๋…„ 7 ์›” 17 ์ผ ๊ธˆ์š”์ผ ์˜ค์ „ 8์‹œ 3 ๋ถ„ Kamil Kisiel [email protected]
์ผ๋‹ค:

@elithrar https://github.com/elithrar ๋‹น์‹ ์ด ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ์†Œ๋ฆฌ์ž…๋‹ˆ๋‹ค
๋‚˜๋ฅผ. ๋ชจ๋“  ๋งค์žฅ์— ๊ฐœ๋ณ„์ ์œผ๋กœ ์ ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ์ ์ด ์•„์‰ฝ์Šต๋‹ˆ๋‹ค.

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/gorilla/sessions/issues/48#issuecomment -122133977.

๋„ค ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์•„์š”. ์—ฌ๊ธฐ์— ๊ฑฐ์Šค๋ฆ„๋ˆ์„ ๋„ฃ์œผ๋ฉด ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ์ƒ์ ์— PR์„ ๋ณด๋‚ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ถ”์  ๋ชฉ์  :

  • [x] [๊ณ ๋ฆด๋ผ / ์„ธ์…˜] (https://github.com/gorilla/sessions)
  • [] [github.com/starJammer/gorilla-sessions-arangodb](https://github.com/starJammer/gorilla-sessions-arangodb)-ArangoDB
  • [] [github.com/yosssi/boltstore](https://github.com/yosssi/boltstore)-๋ณผํŠธ
  • [] [github.com/srinathgs/couchbasestore](https://github.com/srinathgs/couchbasestore)-Couchbase
  • [] [github.com/denizeren/dynamostore](https://github.com/denizeren/dynamostore)-AWS์˜ Dynamodb
  • [] [github.com/bradleypeabody/gorilla-sessions-memcache](https://github.com/bradleypeabody/gorilla-sessions-memcache)-Memcache
  • [] [github.com/hnakamur/gaesessions](https://github.com/hnakamur/gaesessions)-GAE์˜ Memcache
  • [x] [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore)-MongoDB
  • [] [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore)-MySQL
  • [x] [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore)-PostgreSQL
  • [] [github.com/boj/redistore](https://github.com/boj/redistore)-Redis
  • [x] [github.com/boj/rethinkstore](https://github.com/boj/rethinkstore)-RethinkDB
  • [] [github.com/boj/riakstore](https://github.com/boj/riakstore)-Riak
  • [] [github.com/michaeljs1990/sqlitestore](https://github.com/michaeljs1990/sqlitestore)-SQLite

PR์ด ๋ณ‘ํ•ฉ๋˜๋ฉด์ด๋ฅผ ์ถ”์ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์ตœ๊ทผ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฉฐ์น  ํ›„ ์ž๋™์œผ๋กœ ๋‹ซํž™๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ํŒจํ‚ค์ง€์—์„œ ์‹คํ–‰ ํ•œ ํ›„์ด ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๋‹ซ์•„์•ผ ํ•  ๊ฒƒ ๊ฐ™์ง€ ์•Š์Šต๋‹ˆ๋‹ค ... ์ฒดํฌ๋ฆฌ์ŠคํŠธ ๋Š” ํ•ด๋‹น ์ •๋ณด๊ฐ€ ์ตœ์‹ ์ด ์•„๋‹Œ ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ์—ฌ์ „ํžˆ 10 ๋ฒˆ์˜ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ •ํ™•ํ•ด์•ผํ•˜์ง€๋งŒ ๋ชจ๋“  ์ƒ์ ์ด ์ ๊ทน์ ์œผ๋กœ ์œ ์ง€ ๊ด€๋ฆฌ๋˜๊ฑฐ๋‚˜ PR์ด ์ œ์ถœ ๋œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์ตœ๊ทผ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฉฐ์น  ํ›„ ์ž๋™์œผ๋กœ ๋‹ซํž™๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์ตœ๊ทผ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฉฐ์น  ํ›„ ์ž๋™์œผ๋กœ ๋‹ซํž™๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰