-
Notifications
You must be signed in to change notification settings - Fork 6
/
session.go
139 lines (111 loc) · 2.94 KB
/
session.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package manager
import (
"fmt"
"net/http"
"dearcode.net/crab/cache"
"dearcode.net/crab/log"
"github.com/juju/errors"
"dearcode.net/doodle/pkg/manager/config"
)
const (
//session会话超时30分钟
sessionTimeout = 1800
)
type sessionCache struct {
cache *cache.Cache
}
func newSession() *sessionCache {
return &sessionCache{cache: cache.NewCache(sessionTimeout)}
}
func (s *sessionCache) getToken(r *http.Request) (string, error) {
if token := r.URL.Query().Get("token"); token != "" {
return token, nil
}
c, err := r.Cookie(config.Manager.SSO.Key)
if err != nil {
fmt.Printf("key:%v\n", config.Manager.SSO.Key)
return "", errors.Annotatef(err, "key:%s", config.Manager.SSO.Key)
}
return c.Value, nil
}
// verify 调用sso接口验证token返回用户信息.
func (s *sessionCache) verify(r *http.Request, token string) (*userinfo, error) {
resp := struct {
Status int
Message string
Data userinfo
}{}
url := fmt.Sprintf("%s?token=%s", config.Manager.SSO.VerifyURL, token)
log.Debugf("url:%v", url)
if err := httpClient.GetJSON(url, nil, &resp); err != nil {
return nil, errors.Trace(err)
}
if resp.Status != 0 {
return nil, errors.New(resp.Message)
}
return &resp.Data, nil
}
func (u userinfo) String() string {
return u.Email
}
// loadInfo 加载资源与角色信息.
func (u *userinfo) loadInfo() error {
res, err := userdb.loadResource(u.Email)
if err != nil {
return errors.Trace(err)
}
u.setResource(res)
roles, err := userdb.loadRoles(u.Email)
if err != nil {
return errors.Trace(err)
}
u.setRoles(roles)
u.IsAdmin = userdb.isAdmin(u.Email)
return nil
}
func (s *sessionCache) User(w http.ResponseWriter, r *http.Request) (*userinfo, error) {
//如果url中带token字段,说明是rbac回调的
if token := r.URL.Query().Get("token"); token != "" {
cookie := http.Cookie{Name: config.Manager.SSO.Key, Value: token, Path: "/"}
http.SetCookie(w, &cookie)
vals := r.URL.Query()
vals.Del("token")
argv := vals.Encode()
url := r.URL.Path
if argv != "" {
url += "?" + argv
}
w.Header().Add("Location", url)
w.WriteHeader(http.StatusTemporaryRedirect)
log.Infof("%v remove token:%v, location:%v", s, token, url)
return nil, errors.Errorf("retry")
}
token, err := s.getToken(r)
if err != nil {
return nil, errors.Trace(err)
}
log.Debugf("token:%v", token)
if val := s.cache.Get(token); val != nil {
user := val.(*userinfo)
log.Debugf("cache userinfo:%v", user)
return user, user.loadInfo()
}
user, err := s.verify(r, token)
if err != nil {
return nil, errors.Trace(err)
}
cookie := http.Cookie{Name: config.Manager.SSO.Key, Value: token, Path: "/"}
http.SetCookie(w, &cookie)
log.Debugf("userinfo:%+v", user)
if err = user.loadInfo(); err != nil {
return nil, errors.Trace(err)
}
mu, err := userdb.loadUser(user.Email)
if err != nil {
return nil, errors.Trace(err)
}
user.UserID = mu.ID
user.User = mu.Name
s.cache.Add(token, user)
return user, nil
}