Skip to content

Commit 09ee6b2

Browse files
committedOct 23, 2024
chore: 重构Authorizer,减少类型转换
1 parent a14a468 commit 09ee6b2

File tree

14 files changed

+83
-242
lines changed

14 files changed

+83
-242
lines changed
 

‎internal/server/api/web.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (w *Web) Identifier() string {
3434

3535
func (w *Web) Run() error {
3636

37-
authorizer := jwtauth.NewJwtAuth(w.config.JWT)
37+
authorizer := jwtauth.NewJwtAuth[int64](w.config.JWT)
3838
authControl := auth.NewAuth[int64](jwtauth.AuthorizationPrefixBearer, authorizer)
3939

4040
zapLogger := log.ZapLogger().With(logfields.String("module", "api"))

‎internal/server/dash/web.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ const (
4343
)
4444

4545
func (w *Web) Run() error {
46-
authorizer := jwtauth.NewJwtAuth(w.config.AuthJWT)
47-
authRefresher := jwtauth.NewJwtAuth(w.config.RefreshJWT)
46+
authorizer := jwtauth.NewJwtAuth[int64](w.config.AuthJWT)
47+
authRefresher := jwtauth.NewJwtAuth[int64](w.config.RefreshJWT)
4848
authControl := auth.NewAuth[int64](jwtauth.AuthorizationPrefixBearer, authorizer)
4949

5050
zapLogger := log.ZapLogger().With(logfields.String("module", "dash"))

‎internal/service/api/auth.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/tbxark/sphere/internal/pkg/dao"
99
"github.com/tbxark/sphere/internal/pkg/database/ent"
1010
"github.com/tbxark/sphere/internal/pkg/database/ent/userplatform"
11-
"strconv"
1211
"time"
1312
)
1413

@@ -63,7 +62,7 @@ func (s *Service) AuthWxMini(ctx context.Context, req *apiv1.AuthWxMiniRequest)
6362
if err != nil {
6463
return nil, err
6564
}
66-
token, err := s.Authorizer.GenerateToken(strconv.Itoa(int(res.User.Id)), consts.WechatMiniPlatform+":"+wxUser.OpenID)
65+
token, err := s.Authorizer.GenerateToken(res.User.Id, consts.WechatMiniPlatform+":"+wxUser.OpenID)
6766
if err != nil {
6867
return nil, err
6968
}

‎internal/service/api/service.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Service struct {
1818
Cache cache.ByteCache
1919
Wechat *wechat.Wechat
2020
Render *render.Render
21-
Authorizer authorizer.Authorizer
21+
Authorizer authorizer.Authorizer[int64]
2222
Auth *auth.Auth[int64]
2323
httpClient *http.Client
2424
}
@@ -36,7 +36,7 @@ func NewService(db *dao.Dao, wx *wechat.Wechat, store storage.Storage, cache cac
3636
}
3737
}
3838

39-
func (s *Service) Init(auth *auth.Auth[int64], authorizer authorizer.Authorizer) {
39+
func (s *Service) Init(auth *auth.Auth[int64], authorizer authorizer.Authorizer[int64]) {
4040
s.Auth = auth
4141
s.Authorizer = authorizer
4242
}

‎internal/service/dash/auth.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ type AdminToken struct {
2424
type AdminLoginResponseWrapper = ginx.DataResponse[AdminToken]
2525

2626
func (s *Service) createToken(u *ent.Admin) (*AdminToken, error) {
27-
id := strconv.Itoa(int(u.ID))
28-
token, err := s.Authorizer.GenerateToken(id, u.Username, u.Roles...)
27+
token, err := s.Authorizer.GenerateToken(u.ID, u.Username, u.Roles...)
2928
if err != nil {
3029
return nil, err
3130
}
32-
refresh, err := s.AuthRefresher.GenerateToken(id, u.Username)
31+
refresh, err := s.AuthRefresher.GenerateToken(u.ID, u.Username)
3332
if err != nil {
3433
return nil, err
3534
}

‎internal/service/dash/service.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ type Service struct {
1717
WeChat *wechat.Wechat
1818
Render *render.Render
1919

20-
Authorizer authorizer.Authorizer
21-
AuthRefresher authorizer.Authorizer
20+
Authorizer authorizer.Authorizer[int64]
21+
AuthRefresher authorizer.Authorizer[int64]
2222
Auth *auth.Auth[int64]
2323
ACL *auth.ACL
2424
}
@@ -34,7 +34,7 @@ func NewService(db *dao.Dao, wx *wechat.Wechat, store storage.Storage, cache cac
3434
}
3535
}
3636

37-
func (s *Service) Init(auth *auth.Auth[int64], authorizer authorizer.Authorizer, authRefresher authorizer.Authorizer) {
37+
func (s *Service) Init(auth *auth.Auth[int64], authorizer authorizer.Authorizer[int64], authRefresher authorizer.Authorizer[int64]) {
3838
s.Auth = auth
3939
s.Authorizer = authorizer
4040
s.AuthRefresher = authRefresher

‎pkg/server/auth/authorizer/parser.go

+20-13
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
package authorizer
22

3-
import "time"
3+
import (
4+
"golang.org/x/exp/constraints"
5+
"time"
6+
)
47

5-
type Claims struct {
6-
Subject string
7-
Username string
8-
Roles string
9-
Exp int64
8+
type UID interface {
9+
constraints.Integer | string
10+
}
11+
12+
type Claims[T UID] struct {
13+
UID T
14+
Subject string
15+
Roles string
16+
Exp int64
1017
}
1118

1219
type Token struct {
1320
Token string
1421
ExpiresAt time.Time
1522
}
1623

17-
type Parser interface {
18-
ParseToken(token string) (*Claims, error)
24+
type Parser[T UID] interface {
25+
ParseToken(token string) (*Claims[T], error)
1926
ParseRoles(roles string) []string
2027
}
2128

22-
type Generator interface {
23-
GenerateToken(subject, username string, roles ...string) (*Token, error)
29+
type Generator[T UID] interface {
30+
GenerateToken(uid T, subject string, roles ...string) (*Token, error)
2431
}
2532

26-
type Authorizer interface {
27-
Parser
28-
Generator
33+
type Authorizer[T UID] interface {
34+
Parser[T]
35+
Generator[T]
2936
}

‎pkg/server/auth/jwtauth/jwt.go

+30-45
Original file line numberDiff line numberDiff line change
@@ -12,57 +12,48 @@ import (
1212
const (
1313
AuthorizationPrefixBearer = "Bearer"
1414
DefaultTokenDuration = time.Hour * 24 * 7
15-
DefaultRefreshDuration = time.Hour * 24 * 7
1615
)
1716

18-
var _ authorizer.Authorizer = &JwtAuth{}
17+
var _ authorizer.Authorizer[int64] = &JwtAuth[int64]{}
1918

20-
type SignedDetails struct {
19+
type SignedDetails[T authorizer.UID] struct {
2120
jwt.StandardClaims
22-
Username string `json:"username,omitempty"`
23-
Roles string `json:"roles,omitempty"`
21+
UID T `json:"uid,omitempty"`
22+
Roles string `json:"roles,omitempty"`
2423
}
2524

26-
type JwtAuth struct {
27-
secret []byte
28-
signingMethod jwt.SigningMethod
29-
signedTokenDuration time.Duration
30-
signedRefreshDuration time.Duration
31-
mu sync.RWMutex // 添加互斥锁
25+
type JwtAuth[T authorizer.UID] struct {
26+
secret []byte
27+
signingMethod jwt.SigningMethod
28+
signedTokenDuration time.Duration
29+
mu sync.RWMutex // 添加互斥锁
3230
}
3331

34-
type Option func(*JwtAuth)
32+
type Option[T authorizer.UID] func(*JwtAuth[T])
3533

36-
func NewJwtAuth(secret string, opts ...Option) *JwtAuth {
37-
ja := &JwtAuth{
38-
secret: []byte(secret),
39-
signingMethod: jwt.SigningMethodHS256,
40-
signedTokenDuration: DefaultTokenDuration,
41-
signedRefreshDuration: DefaultRefreshDuration,
34+
func NewJwtAuth[T authorizer.UID](secret string, opts ...Option[T]) *JwtAuth[T] {
35+
ja := &JwtAuth[T]{
36+
secret: []byte(secret),
37+
signingMethod: jwt.SigningMethodHS256,
38+
signedTokenDuration: DefaultTokenDuration,
4239
}
4340
for _, opt := range opts {
4441
opt(ja)
4542
}
4643
return ja
4744
}
4845

49-
func WithTokenDuration(d time.Duration) Option {
50-
return func(ja *JwtAuth) {
46+
func WithTokenDuration[T authorizer.UID](d time.Duration) Option[T] {
47+
return func(ja *JwtAuth[T]) {
5148
ja.signedTokenDuration = d
5249
}
5350
}
5451

55-
func WithRefreshTokenDuration(d time.Duration) Option {
56-
return func(ja *JwtAuth) {
57-
ja.signedRefreshDuration = d
58-
}
59-
}
60-
61-
func (g *JwtAuth) GenerateToken(subject, username string, roles ...string) (*authorizer.Token, error) {
52+
func (g *JwtAuth[T]) GenerateToken(uid T, subject string, roles ...string) (*authorizer.Token, error) {
6253
expiresAt := time.Now().Local().Add(g.signedTokenDuration)
63-
claims := &SignedDetails{
64-
Username: username,
65-
Roles: strings.Join(roles, ","),
54+
claims := &SignedDetails[T]{
55+
UID: uid,
56+
Roles: strings.Join(roles, ","),
6657
StandardClaims: jwt.StandardClaims{
6758
Subject: subject,
6859
ExpiresAt: expiresAt.Unix(),
@@ -80,8 +71,8 @@ func (g *JwtAuth) GenerateToken(subject, username string, roles ...string) (*aut
8071
}, nil
8172
}
8273

83-
func (g *JwtAuth) ParseToken(signedToken string) (*authorizer.Claims, error) {
84-
claims := &SignedDetails{}
74+
func (g *JwtAuth[T]) ParseToken(signedToken string) (*authorizer.Claims[T], error) {
75+
claims := &SignedDetails[T]{}
8576
_, err := jwt.ParseWithClaims(signedToken, claims, func(token *jwt.Token) (interface{}, error) {
8677
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
8778
return nil, jwt.ErrSignatureInvalid
@@ -91,26 +82,20 @@ func (g *JwtAuth) ParseToken(signedToken string) (*authorizer.Claims, error) {
9182
if err != nil {
9283
return nil, err
9384
}
94-
return &authorizer.Claims{
95-
Subject: claims.Subject,
96-
Username: claims.Username,
97-
Roles: claims.Roles,
98-
Exp: claims.ExpiresAt,
85+
return &authorizer.Claims[T]{
86+
UID: claims.UID,
87+
Subject: claims.Subject,
88+
Roles: claims.Roles,
89+
Exp: claims.ExpiresAt,
9990
}, nil
10091
}
10192

102-
func (g *JwtAuth) ParseRoles(roles string) []string {
93+
func (g *JwtAuth[T]) ParseRoles(roles string) []string {
10394
return strings.Split(roles, ",")
10495
}
10596

106-
func (g *JwtAuth) SetTokenDuration(duration time.Duration) {
97+
func (g *JwtAuth[T]) SetTokenDuration(duration time.Duration) {
10798
g.mu.Lock()
10899
defer g.mu.Unlock()
109100
g.signedTokenDuration = duration
110101
}
111-
112-
func (g *JwtAuth) SetRefreshTokenDuration(duration time.Duration) {
113-
g.mu.Lock()
114-
defer g.mu.Unlock()
115-
g.signedRefreshDuration = duration
116-
}

‎pkg/server/auth/jwtauth/jwt_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
)
77

88
func TestJwtAuth_ParseToken(t *testing.T) {
9-
auth := NewJwtAuth("secret")
9+
auth := NewJwtAuth[string]("secret")
1010
token, err := auth.GenerateToken("1", "username", "admin")
1111
if err != nil {
1212
t.Error(err)
@@ -15,14 +15,14 @@ func TestJwtAuth_ParseToken(t *testing.T) {
1515
if err != nil {
1616
t.Error(err)
1717
}
18-
if claims.Username != "username" {
19-
t.Error("username not match")
18+
if claims.Subject != "username" {
19+
t.Error("subject not match")
2020
}
2121
if claims.Roles != "admin" {
2222
t.Error("roles not match")
2323
}
24-
if claims.Subject != "1" {
25-
t.Error("subject not match")
24+
if claims.UID != "1" {
25+
t.Error("uid not match")
2626
}
2727
auth.SetTokenDuration(0)
2828
token, err = auth.GenerateToken("1", "username", "admin")

‎pkg/server/auth/tmaauth/tma.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package tmaauth
33
import (
44
"github.com/tbxark/sphere/pkg/server/auth/authorizer"
55
initdata "github.com/telegram-mini-apps/init-data-golang"
6-
"strconv"
76
"time"
87
)
98

109
const AuthorizationPrefixTMA = "tma"
1110

12-
var _ authorizer.Parser = &TmaAuth{}
11+
var _ authorizer.Parser[int64] = &TmaAuth{}
1312

1413
type TmaAuth struct {
1514
token string
@@ -23,7 +22,7 @@ func NewTmaAuth(token string) *TmaAuth {
2322
}
2423
}
2524

26-
func (t *TmaAuth) ParseToken(token string) (*authorizer.Claims, error) {
25+
func (t *TmaAuth) ParseToken(token string) (*authorizer.Claims[int64], error) {
2726
err := initdata.Validate(token, t.token, t.expIn)
2827
if err != nil {
2928
return nil, err
@@ -32,11 +31,11 @@ func (t *TmaAuth) ParseToken(token string) (*authorizer.Claims, error) {
3231
if err != nil {
3332
return nil, err
3433
}
35-
return &authorizer.Claims{
36-
Subject: strconv.Itoa(int(initData.Chat.ID)),
37-
Username: initData.Chat.Username,
38-
Roles: string(initData.Chat.Type),
39-
Exp: initData.AuthDate().Add(t.expIn).Unix(),
34+
return &authorizer.Claims[int64]{
35+
UID: initData.Chat.ID,
36+
Subject: initData.Chat.Username,
37+
Roles: string(initData.Chat.Type),
38+
Exp: initData.AuthDate().Add(t.expIn).Unix(),
4039
}, nil
4140
}
4241

‎pkg/server/middleware/auth/auth.go

+7-12
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ package auth
33
import (
44
"context"
55
"github.com/tbxark/sphere/pkg/server/auth/authorizer"
6-
"golang.org/x/exp/constraints"
76
)
87

98
const (
10-
ContextKeyID = "uid"
11-
ContextKeyUsername = "username"
9+
ContextKeyUID = "uid"
10+
ContextKeySubject = "subject"
1211
ContextKeyRoles = "roles"
1312
AuthorizationHeader = "Authorization"
1413
)
@@ -31,29 +30,25 @@ var (
3130
PermissionError = Error{403, "permission denied"}
3231
)
3332

34-
type ID interface {
35-
constraints.Integer | string
36-
}
37-
38-
type Auth[I ID] struct {
33+
type Auth[I authorizer.UID] struct {
3934
zeroID I
4035
prefix string
41-
parser authorizer.Parser
36+
parser authorizer.Parser[I]
4237
}
4338

4439
type AccessControl interface {
4540
IsAllowed(role, resource string) bool
4641
}
4742

48-
func NewAuth[I ID](prefix string, parser authorizer.Parser) *Auth[I] {
43+
func NewAuth[I authorizer.UID](prefix string, parser authorizer.Parser[I]) *Auth[I] {
4944
return &Auth[I]{
5045
prefix: prefix,
5146
parser: parser,
5247
}
5348
}
5449

5550
func (a *Auth[I]) GetCurrentID(ctx context.Context) (I, error) {
56-
raw := ctx.Value(ContextKeyID)
51+
raw := ctx.Value(ContextKeyUID)
5752
if raw == nil {
5853
return a.zeroID, NeedLoginError
5954
}
@@ -65,7 +60,7 @@ func (a *Auth[I]) GetCurrentID(ctx context.Context) (I, error) {
6560
}
6661

6762
func (a *Auth[I]) GetCurrentUsername(ctx context.Context) (string, error) {
68-
raw := ctx.Value(ContextKeyUsername)
63+
raw := ctx.Value(ContextKeySubject)
6964
username, ok := raw.(string)
7065
if !ok {
7166
return "", NeedLoginError

0 commit comments

Comments
 (0)