user_auth.go
3.6 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package userAuth
import (
"encoding/json"
"fmt"
"github.com/tiptok/gocomm/pkg/redis"
"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/utils"
"strconv"
)
var (
errDataType = fmt.Errorf("auth:data type assert error")
errNoMatch = fmt.Errorf("auth:user auth no match")
errNotFound = func(field string) error { return fmt.Errorf("auth:hset field (%v) not found", field) }
errTokenNotEqual = func(target, compare string) error {
return fmt.Errorf("auth:token not equal (%v != %v)", target, compare)
}
)
type UserAuthManager interface {
//添加用户权限
AddAuth() error
//获取用户权限
GetAuth() (interface{}, error)
//移除用户权限
RemoveAuth() error
//检验权限
//检查 refreshToken assessToken 是否一致
Check(*Options) error
//用户权限是否存在
//true:存在 false:不存在
Exist() bool
}
var _ UserAuthManager = (*RedisUserAuth)(nil)
type Options struct {
UserId int64
RefreshToken string
AccessToken string
}
func NewOptions(options ...Option) *Options {
Options := &Options{}
for i := range options {
options[i](Options)
}
return Options
}
type Option func(options *Options)
//option 参数
func WithRefreshToken(token string) Option {
return func(options *Options) {
options.RefreshToken = token
}
}
func WithAccessToken(token string) Option {
return func(options *Options) {
options.AccessToken = token
}
}
func WithUserId(uid int64) Option {
return func(options *Options) {
options.UserId = uid
}
}
//Redis用户权限
type RedisUserAuth struct {
Options *Options
}
func NewRedisUserAuth(options ...Option) *RedisUserAuth {
rua := &RedisUserAuth{
Options: NewOptions(options...),
}
return rua
}
func (auth RedisUserAuth) AddAuth() error {
err := redis.Hset(
auth.redisKey(),
auth.field(),
utils.JsonAssertString(NewRedisUserAuthData(auth.Options)), 0,
)
return err
}
func (auth RedisUserAuth) RemoveAuth() error {
if !auth.Exist() {
return nil
}
return redis.Hdel(auth.redisKey(), auth.field())
}
func (auth RedisUserAuth) GetAuth() (interface{}, error) {
if !auth.Exist() {
return nil, errNotFound(auth.field())
}
data, err := redis.Hget(auth.redisKey(), auth.field())
if err != nil {
return nil, err
}
var authData *RedisUserAuthData
if err = json.Unmarshal([]byte(data), &authData); err != nil {
return nil, err
}
return authData, nil
}
func (auth RedisUserAuth) Check(options *Options) error {
data, err := auth.GetAuth()
if err != nil {
return err
}
authData, ok := data.(*RedisUserAuthData)
if !ok {
return errDataType
}
if options.AccessToken != "" {
if authData.AccessToken != options.AccessToken {
return errTokenNotEqual(authData.AccessToken, options.AccessToken)
}
return nil
}
if options.RefreshToken != "" {
if authData.RefreshToken != options.RefreshToken {
return errTokenNotEqual(authData.RefreshToken, options.RefreshToken)
}
return nil
}
return errNoMatch
}
func (auth RedisUserAuth) Exist() bool {
return redis.Hexists(auth.redisKey(), auth.field())
}
func (auth RedisUserAuth) redisKey() string {
if auth.Options.UserId == 0 {
return ""
}
return utils.RedisKey("user_auth")
}
func (auth RedisUserAuth) field() string {
return strconv.Itoa(int(auth.Options.UserId))
}
//存储到redis的数据结构
type RedisUserAuthData struct {
UserId int64 `json:"userId"`
RefreshToken string `json:"refreshToken"`
AccessToken string `json:"accessToken"`
}
func NewRedisUserAuthData(options *Options) RedisUserAuthData {
return RedisUserAuthData{
UserId: options.UserId,
RefreshToken: options.RefreshToken,
AccessToken: options.AccessToken,
}
}