You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We know that we can save sessions in many ways including in memory, the file system or directly into the database. We need to define a `Provider` interface in order to represent the underlying structure of our session manager:
62
-
62
+
```Go
63
63
typeProviderinterface {
64
64
SessionInit(sid string) (Session, error)
65
65
SessionRead(sid string) (Session, error)
66
66
SessionDestroy(sid string) error
67
67
SessionGC(maxLifeTime int64)
68
68
}
69
-
69
+
```
70
70
-`SessionInit` implements the initialization of a session, and returns a new session if it succeeds.
71
71
-`SessionRead` returns a session represented by the corresponding sid. Creates a new session and returns it if it does not already exist.
72
72
-`SessionDestroy` given an sid, deletes the corresponding session.
73
73
-`SessionGC` deletes expired session variables according to `maxLifeTime`.
74
74
75
75
So what methods should our session interface have? If you have any experience in web development, you should know that there are only four operations for sessions: set value, get value, delete value and get current session id. So, our session interface should have four methods to perform these operations.
76
-
76
+
```Go
77
77
typeSessioninterface {
78
78
Set(key, value interface{}) error//set session value
79
79
Get(key interface{}) interface{} //get session value
80
80
Delete(key interface{}) error//delete session value
81
81
SessionID() string//back current sessionID
82
82
}
83
-
83
+
```
84
84
This design takes its roots from the `database/sql/driver`, which defines the interface first, then registers specific structures when we want to use it. The following code is the internal implementation of a session register function.
85
-
85
+
```Go
86
86
varprovides = make(map[string]Provider)
87
87
88
88
// Register makes a session provider available by the provided name.
@@ -97,23 +97,23 @@ This design takes its roots from the `database/sql/driver`, which defines the in
97
97
}
98
98
provides[name] = provider
99
99
}
100
-
100
+
```
101
101
### Unique session id's
102
102
103
103
Session id's are for identifying users of web applications, so they must be unique. The following code shows how to achieve this goal:
We need to allocate or get an existing session in order to validate user operations. The `SessionStart` function is for checking the existence of any sessions related to the current user, and creating a new session if none is found.
116
-
116
+
```Go
117
117
func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Session) {
118
118
manager.lock.Lock()
119
119
defer manager.lock.Unlock()
@@ -129,9 +129,9 @@ We need to allocate or get an existing session in order to validate user operati
129
129
}
130
130
return
131
131
}
132
-
132
+
```
133
133
Here is an example that uses sessions for a login operation.
134
-
134
+
```Go
135
135
funclogin(whttp.ResponseWriter, r *http.Request) {
136
136
sess:= globalSessions.SessionStart(w, r)
137
137
r.ParseForm()
@@ -144,13 +144,13 @@ Here is an example that uses sessions for a login operation.
144
144
http.Redirect(w, r, "/", 302)
145
145
}
146
146
}
147
-
147
+
```
148
148
### Operation value: set, get and delete
149
149
150
150
The `SessionStart` function returns a variable that implements a session interface. How do we use it?
151
151
152
152
You saw `session.Get("uid")` in the above example for a basic operation. Now let's examine a more detailed example.
153
-
153
+
```Go
154
154
funccount(whttp.ResponseWriter, r *http.Request) {
155
155
sess:= globalSessions.SessionStart(w, r)
156
156
createtime:= sess.Get("createtime")
@@ -170,16 +170,16 @@ You saw `session.Get("uid")` in the above example for a basic operation. Now let
170
170
w.Header().Set("Content-Type", "text/html")
171
171
t.Execute(w, sess.Get("countnum"))
172
172
}
173
-
173
+
```
174
174
As you can see, operating on sessions simply involves using the key/value pattern in the Set, Get and Delete operations.
175
175
176
176
Because sessions have the concept of an expiry time, we define the GC to update the session's latest modify time. This way, the GC will not delete sessions that have expired but are still being used.
177
177
178
178
### Reset sessions
179
179
180
180
We know that web applications have a logout operation. When users logout, we need to delete the corresponding session. We've already used the reset operation in above example -now let's take a look at the function body.
181
-
182
-
//Destroy sessionid
181
+
```Go
182
+
//Destroy sessionid
183
183
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request){
184
184
cookie, err:= r.Cookie(manager.cookieName)
185
185
if err != nil || cookie.Value == "" {
@@ -193,11 +193,11 @@ We know that web applications have a logout operation. When users logout, we nee
193
193
http.SetCookie(w, &cookie)
194
194
}
195
195
}
196
-
196
+
```
197
197
### Delete sessions
198
198
199
199
Let's see how to let the session manager delete a session. We need to start the GC in the `main()` function:
200
-
200
+
```Go
201
201
funcinit() {
202
202
go globalSessions.GC()
203
203
}
@@ -208,7 +208,7 @@ Let's see how to let the session manager delete a session. We need to start the
We see that the GC makes full use of the timer function in the `time` package. It automatically calls GC when the session times out, ensuring that all sessions are usable during `maxLifeTime`. A similar solution can be used to count online users.
Copy file name to clipboardExpand all lines: en/06.3.md
+6-6Lines changed: 6 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# 6.3 Session storage
2
2
3
3
We introduced a simple session manager's working principles in the previous section, and among other things, we defined a session storage interface. In this section, I'm going to show you an example of a memory based session storage engine that implements this interface. You can tailor this to other forms of session storage as well.
4
-
4
+
```Go
5
5
package memory
6
6
7
7
import (
@@ -114,24 +114,24 @@ We introduced a simple session manager's working principles in the previous sect
114
114
session.Register("memory", pder)
115
115
}
116
116
117
-
117
+
```
118
118
The above example implements a memory based session storage mechanism. It uses its `init()` function to register this storage engine to the session manager. So how do we register this engine from our main program?
119
-
119
+
```Go
120
120
import (
121
121
"github.com/astaxie/session"
122
122
_ "github.com/astaxie/session/providers/memory"
123
123
)
124
-
124
+
```
125
125
We use the blank import mechanism (which will invoke the package's `init()` function automatically) to register this engine to a session manager. We then use the following code to initialize the session manager:
Copy file name to clipboardExpand all lines: en/06.4.md
+6-6Lines changed: 6 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ In this section, we are going to show you how to hijack a session for educationa
7
7
## The session hijacking process
8
8
9
9
The following code is a counter for the `count` variable:
10
-
10
+
```Go
11
11
funccount(whttp.ResponseWriter, r *http.Request) {
12
12
sess:= globalSessions.SessionStart(w, r)
13
13
ct:= sess.Get("countnum")
@@ -20,7 +20,7 @@ The following code is a counter for the `count` variable:
20
20
w.Header().Set("Content-Type", "text/html")
21
21
t.Execute(w, sess.Get("countnum"))
22
22
}
23
-
23
+
```
24
24
The content of `count.gtpl` is as follows:
25
25
26
26
Hi. Now count:{{.}}
@@ -60,7 +60,7 @@ Through this simple example of hijacking a session, you can see that it's very d
60
60
The first step is to only set session id's in cookies, instead of in URL rewrites. Also, we should set the httponly cookie property to true. This restricts client-side scripts from gaining access to the session id. Using these techniques, cookies cannot be accessed by XSS and it won't be as easy as we demonstrated to get a session id from a cookie manager.
61
61
62
62
The second step is to add a token to every request. Similar to the manner in which we dealt with repeating form submissions in previous sections, we add a hidden field that contains a token. When a request is sent to the server, we can verify this token to prove that the request is unique.
63
-
63
+
```Go
64
64
h:= md5.New()
65
65
salt:="astaxie%^7&8888"
66
66
io.WriteString(h,salt+time.Now().String())
@@ -69,19 +69,19 @@ The second step is to add a token to every request. Similar to the manner in whi
69
69
// ask to log in
70
70
}
71
71
sess.Set("token",token)
72
-
72
+
```
73
73
### Session id timeout
74
74
75
75
Another solution is to add a create time for every session, and to replace expired session id's with new ones. This can prevent session hijacking under certain circumstances such as when the hijack is attempted too late.
We set a value to save the create time and check if it's expired (I set 60 seconds here). This step can often thwart session hijacking attempts.
86
86
87
87
By combining the two solutions set out above you will be able to prevent most session hijacking attempts from succeeding. On the one hand, session id's that are frequently reset will result in an attacker always getting expired and useless session id's; on the other hand, by setting the httponly property on cookies and ensuring that session id's can only be passed via cookies, all URL based attacks are mitigated. Finally, we set `MaxAge=0` on our cookies, which means that the session id's will not be saved in the browser history.
0 commit comments