Skip to content

Base64 URLEncoding could generate "-", So it's not safe to use "--" as sign separator. I encounter this tricky bug quite frequently #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 26, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package mango

import (
"bytes"
"hash"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/gob"
"fmt"
"hash"
"io/ioutil"
"encoding/gob"
"net/http"
"strings"
)
Expand Down Expand Up @@ -50,7 +50,7 @@ func decode64(value string) (result string) {
func decodeCookie(value, secret string) (cookie map[string]interface{}) {
cookie = make(map[string]interface{})

split := strings.Split(string(value), "--")
split := strings.Split(string(value), "/")

if len(split) < 2 {
return cookie
Expand Down Expand Up @@ -91,7 +91,7 @@ func encode64(value string) (result string) {
func encodeCookie(value map[string]interface{}, secret string) (cookie string) {
data := encodeGob(value)

return fmt.Sprintf("%s--%s", encode64(data), encode64(hashCookie(data, secret)))
return fmt.Sprintf("%s/%s", encode64(data), encode64(hashCookie(data, secret)))
}

func prepareSession(env Env, key, secret string) {
Expand All @@ -106,19 +106,31 @@ func prepareSession(env Env, key, secret string) {
env["mango.session"] = make(map[string]interface{})
}

func commitSession(headers Headers, env Env, key, secret, domain string) {
func commitSession(headers Headers, env Env, key, secret string, options *CookieOptions) {
cookie := new(http.Cookie)
cookie.Name = key
cookie.Value = encodeCookie(env["mango.session"].(map[string]interface{}), secret)
cookie.Domain = domain
cookie.Path = options.Path
cookie.Domain = options.Domain
cookie.MaxAge = options.MaxAge
cookie.Secure = options.Secure
cookie.HttpOnly = options.HttpOnly
headers.Add("Set-Cookie", cookie.String())
}

func Sessions(secret, key, domain string) Middleware {
type CookieOptions struct {
Domain string
Path string
MaxAge int
Secure bool
HttpOnly bool
}

func Sessions(secret, key string, options *CookieOptions) Middleware {
return func(env Env, app App) (status Status, headers Headers, body Body) {
prepareSession(env, key, secret)
status, headers, body = app(env)
commitSession(headers, env, key, secret, domain)
commitSession(headers, env, key, secret, options)
return status, headers, body
}
}
4 changes: 2 additions & 2 deletions sessions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestSessions(t *testing.T) {

// Compile the stack
sessionsStack := new(Stack)
sessionsStack.Middleware(Sessions("my_secret", "my_key", ".my.domain.com"))
sessionsStack.Middleware(Sessions("my_secret", "my_key", &CookieOptions{Domain: ".my.domain.com"}))
sessionsApp := sessionsStack.Compile(sessionsTestServer)

// Request against it
Expand Down Expand Up @@ -83,7 +83,7 @@ func BenchmarkSessions(b *testing.B) {
}

sessionsStack := new(Stack)
sessionsStack.Middleware(Sessions("my_secret", "my_key", ".my.domain.com"))
sessionsStack.Middleware(Sessions("my_secret", "my_key", &CookieOptions{Domain: ".my.domain.com"}))
sessionsApp := sessionsStack.Compile(sessionsTestServer)

request, _ := http.NewRequest("GET", "http://localhost:3000/", nil)
Expand Down