sess_cookie.go 4.73 KB
Newer Older
1
// Copyright 2014 beego Author. All Rights Reserved.
2
//
3 4 5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9 10 11 12 13 14
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

astaxie's avatar
astaxie committed
15 16 17 18 19 20 21 22 23 24 25 26 27
package session

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/json"
	"net/http"
	"net/url"
	"sync"
)

var cookiepder = &CookieProvider{}

astaxie's avatar
astaxie committed
28
// CookieSessionStore Cookie SessionStore
astaxie's avatar
astaxie committed
29 30
type CookieSessionStore struct {
	sid    string
31
	values map[interface{}]interface{} // session data
astaxie's avatar
astaxie committed
32 33 34
	lock   sync.RWMutex
}

35 36
// Set value to cookie session.
// the value are encoded as gob with hash block string.
astaxie's avatar
astaxie committed
37 38 39 40 41 42 43
func (st *CookieSessionStore) Set(key, value interface{}) error {
	st.lock.Lock()
	defer st.lock.Unlock()
	st.values[key] = value
	return nil
}

44
// Get value from cookie session
astaxie's avatar
astaxie committed
45 46 47 48 49 50
func (st *CookieSessionStore) Get(key interface{}) interface{} {
	st.lock.RLock()
	defer st.lock.RUnlock()
	if v, ok := st.values[key]; ok {
		return v
	}
astaxie's avatar
astaxie committed
51
	return nil
astaxie's avatar
astaxie committed
52 53
}

54
// Delete value in cookie session
astaxie's avatar
astaxie committed
55 56 57 58 59 60 61
func (st *CookieSessionStore) Delete(key interface{}) error {
	st.lock.Lock()
	defer st.lock.Unlock()
	delete(st.values, key)
	return nil
}

astaxie's avatar
astaxie committed
62
// Flush Clean all values in cookie session
astaxie's avatar
astaxie committed
63 64 65 66 67 68 69
func (st *CookieSessionStore) Flush() error {
	st.lock.Lock()
	defer st.lock.Unlock()
	st.values = make(map[interface{}]interface{})
	return nil
}

astaxie's avatar
astaxie committed
70
// SessionID Return id of this cookie session
astaxie's avatar
astaxie committed
71 72 73 74
func (st *CookieSessionStore) SessionID() string {
	return st.sid
}

astaxie's avatar
astaxie committed
75
// SessionRelease Write cookie session to http response cookie
astaxie's avatar
astaxie committed
76
func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
Faissal Elamraoui's avatar
Faissal Elamraoui committed
77 78 79 80 81 82 83 84 85
	encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values)
	if err == nil {
		cookie := &http.Cookie{Name: cookiepder.config.CookieName,
			Value:    url.QueryEscape(encodedCookie),
			Path:     "/",
			HttpOnly: true,
			Secure:   cookiepder.config.Secure,
			MaxAge:   cookiepder.config.Maxage}
		http.SetCookie(w, cookie)
astaxie's avatar
astaxie committed
86 87 88 89 90 91 92 93 94 95 96 97
	}
}

type cookieConfig struct {
	SecurityKey  string `json:"securityKey"`
	BlockKey     string `json:"blockKey"`
	SecurityName string `json:"securityName"`
	CookieName   string `json:"cookieName"`
	Secure       bool   `json:"secure"`
	Maxage       int    `json:"maxage"`
}

astaxie's avatar
astaxie committed
98
// CookieProvider Cookie session provider
astaxie's avatar
astaxie committed
99 100 101 102 103 104
type CookieProvider struct {
	maxlifetime int64
	config      *cookieConfig
	block       cipher.Block
}

astaxie's avatar
astaxie committed
105
// SessionInit Init cookie session provider with max lifetime and config json.
106 107 108 109 110 111 112
// maxlifetime is ignored.
// json config:
// 	securityKey - hash string
// 	blockKey - gob encode hash string. it's saved as aes crypto.
// 	securityName - recognized name in encoded cookie string
// 	cookieName - cookie name
// 	maxage - cookie max life time.
astaxie's avatar
astaxie committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error {
	pder.config = &cookieConfig{}
	err := json.Unmarshal([]byte(config), pder.config)
	if err != nil {
		return err
	}
	if pder.config.BlockKey == "" {
		pder.config.BlockKey = string(generateRandomKey(16))
	}
	if pder.config.SecurityName == "" {
		pder.config.SecurityName = string(generateRandomKey(20))
	}
	pder.block, err = aes.NewCipher([]byte(pder.config.BlockKey))
	if err != nil {
		return err
	}
asta.xie's avatar
asta.xie committed
129
	pder.maxlifetime = maxlifetime
astaxie's avatar
astaxie committed
130 131 132
	return nil
}

astaxie's avatar
astaxie committed
133
// SessionRead Get SessionStore in cooke.
134
// decode cooke string to map and put into SessionStore with sid.
astaxie's avatar
astaxie committed
135
func (pder *CookieProvider) SessionRead(sid string) (Store, error) {
astaxie's avatar
astaxie committed
136
	maps, _ := decodeCookie(pder.block,
astaxie's avatar
astaxie committed
137 138 139
		pder.config.SecurityKey,
		pder.config.SecurityName,
		sid, pder.maxlifetime)
astaxie's avatar
astaxie committed
140 141 142 143
	if maps == nil {
		maps = make(map[interface{}]interface{})
	}
	rs := &CookieSessionStore{sid: sid, values: maps}
astaxie's avatar
astaxie committed
144 145 146
	return rs, nil
}

astaxie's avatar
astaxie committed
147
// SessionExist Cookie session is always existed
astaxie's avatar
astaxie committed
148 149 150 151
func (pder *CookieProvider) SessionExist(sid string) bool {
	return true
}

astaxie's avatar
astaxie committed
152 153
// SessionRegenerate Implement method, no used.
func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
astaxie's avatar
astaxie committed
154 155 156
	return nil, nil
}

astaxie's avatar
astaxie committed
157
// SessionDestroy Implement method, no used.
astaxie's avatar
astaxie committed
158 159 160 161
func (pder *CookieProvider) SessionDestroy(sid string) error {
	return nil
}

astaxie's avatar
astaxie committed
162
// SessionGC Implement method, no used.
astaxie's avatar
astaxie committed
163 164 165
func (pder *CookieProvider) SessionGC() {
}

astaxie's avatar
astaxie committed
166
// SessionAll Implement method, return 0.
astaxie's avatar
astaxie committed
167 168 169 170
func (pder *CookieProvider) SessionAll() int {
	return 0
}

astaxie's avatar
astaxie committed
171
// SessionUpdate Implement method, no used.
astaxie's avatar
astaxie committed
172 173 174 175 176 177 178
func (pder *CookieProvider) SessionUpdate(sid string) error {
	return nil
}

func init() {
	Register("cookie", cookiepder)
}