diff --git a/README.md b/README.md index 712e5bc..99eb3e8 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,6 @@ - 页面 提取记录 - 页面 使用记录 -- 保存 session 到数据库 -- 移除 PayloadType,使用 Grant_Type - ### 长效业务 - 支付回调处理 diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index 5f24e0e..100fb89 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -628,7 +628,6 @@ create table channel ( node_host varchar(255), protocol int, auth_ip bool not null default false, - user_host varchar(255), auth_pass bool not null default false, username varchar(255), password varchar(255), @@ -644,7 +643,6 @@ create index channel_proxy_host_index on channel (proxy_host); create index channel_proxy_port_index on channel (proxy_port); create index channel_node_host_index on channel (node_host); create index channel_auth_ip_index on channel (auth_ip); -create index channel_user_host_index on channel (user_host); create index channel_auth_pass_index on channel (auth_pass); create index channel_username_index on channel (username); create index channel_expiration_index on channel (expiration); @@ -661,7 +659,6 @@ comment on column channel.proxy_port is '转发端口'; comment on column channel.node_host is '节点地址'; comment on column channel.protocol is '协议类型:1-http,2-https,3-socks5'; comment on column channel.auth_ip is 'IP认证'; -comment on column channel.user_host is '用户地址'; comment on column channel.auth_pass is '密码认证'; comment on column channel.username is '用户名'; comment on column channel.password is '密码'; diff --git a/web/models/channel.gen.go b/web/models/channel.gen.go index dbf7bc0..fa3c89f 100644 --- a/web/models/channel.gen.go +++ b/web/models/channel.gen.go @@ -23,7 +23,6 @@ type Channel struct { NodeHost string `gorm:"column:node_host;comment:节点地址" json:"node_host"` // 节点地址 Protocol int32 `gorm:"column:protocol;comment:协议类型:1-http,2-https,3-socks5" json:"protocol"` // 协议类型:1-http,2-https,3-socks5 AuthIP bool `gorm:"column:auth_ip;not null;comment:IP认证" json:"auth_ip"` // IP认证 - UserHost string `gorm:"column:user_host;comment:用户地址" json:"user_host"` // 用户地址 AuthPass bool `gorm:"column:auth_pass;not null;comment:密码认证" json:"auth_pass"` // 密码认证 Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名 Password string `gorm:"column:password;comment:密码" json:"password"` // 密码 diff --git a/web/queries/channel.gen.go b/web/queries/channel.gen.go index db0aef6..6865498 100644 --- a/web/queries/channel.gen.go +++ b/web/queries/channel.gen.go @@ -36,7 +36,6 @@ func newChannel(db *gorm.DB, opts ...gen.DOOption) channel { _channel.NodeHost = field.NewString(tableName, "node_host") _channel.Protocol = field.NewInt32(tableName, "protocol") _channel.AuthIP = field.NewBool(tableName, "auth_ip") - _channel.UserHost = field.NewString(tableName, "user_host") _channel.AuthPass = field.NewBool(tableName, "auth_pass") _channel.Username = field.NewString(tableName, "username") _channel.Password = field.NewString(tableName, "password") @@ -63,7 +62,6 @@ type channel struct { NodeHost field.String // 节点地址 Protocol field.Int32 // 协议类型:1-http,2-https,3-socks5 AuthIP field.Bool // IP认证 - UserHost field.String // 用户地址 AuthPass field.Bool // 密码认证 Username field.String // 用户名 Password field.String // 密码 @@ -96,7 +94,6 @@ func (c *channel) updateTableName(table string) *channel { c.NodeHost = field.NewString(table, "node_host") c.Protocol = field.NewInt32(table, "protocol") c.AuthIP = field.NewBool(table, "auth_ip") - c.UserHost = field.NewString(table, "user_host") c.AuthPass = field.NewBool(table, "auth_pass") c.Username = field.NewString(table, "username") c.Password = field.NewString(table, "password") @@ -120,7 +117,7 @@ func (c *channel) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (c *channel) fillFieldMap() { - c.fieldMap = make(map[string]field.Expr, 17) + c.fieldMap = make(map[string]field.Expr, 16) c.fieldMap["id"] = c.ID c.fieldMap["user_id"] = c.UserID c.fieldMap["proxy_id"] = c.ProxyID @@ -130,7 +127,6 @@ func (c *channel) fillFieldMap() { c.fieldMap["node_host"] = c.NodeHost c.fieldMap["protocol"] = c.Protocol c.fieldMap["auth_ip"] = c.AuthIP - c.fieldMap["user_host"] = c.UserHost c.fieldMap["auth_pass"] = c.AuthPass c.fieldMap["username"] = c.Username c.fieldMap["password"] = c.Password diff --git a/web/services/channel.go b/web/services/channel.go index 637f23a..4861db7 100644 --- a/web/services/channel.go +++ b/web/services/channel.go @@ -3,7 +3,6 @@ package services import ( "context" "database/sql" - "encoding/json" "errors" "fmt" "log/slog" @@ -97,12 +96,6 @@ func (s *channelService) RemoveChannels(ctx context.Context, authCtx *auth.Conte return ChannelServiceErr("删除通道失败") } - // 删除缓存 - err = deleteCache(ctx, channels) - if err != nil { - return err - } - // 禁用代理端口并下线用过的节点 if env.DebugExternalChange { var step = time.Now() @@ -276,7 +269,7 @@ func (s *channelService) CreateChannel( } // 缓存通道数据 - err = cacheChannels(ctx, rid, newChannels) + err = cacheChannels(ctx, rid, newChannels, whitelist) if err != nil { return err } @@ -612,8 +605,28 @@ func saveChannels(channels []*m.Channel) (err error) { return nil } -func cacheChannels(ctx context.Context, rid string, channels []*m.Channel) (err error) { - err = cache(ctx, channels) +func cacheChannels(ctx context.Context, rid string, channels []*m.Channel, whitelists *[]string) (err error) { + if len(channels) == 0 { + return nil + } + + pipe := g.Redis.TxPipeline() + + zList := make([]redis.Z, 0, len(channels)) + for _, channel := range channels { + expiration := time.Time(channel.Expiration) + keys := chAuthItems(channel, whitelists) + for _, key := range keys { + pipe.Set(ctx, key, true, time.Since(expiration)) + } + zList = append(zList, redis.Z{ + Score: float64(expiration.Unix()), + Member: channel.ID, + }) + } + pipe.ZAdd(ctx, "tasks:channel", zList...) + + _, err = pipe.Exec(ctx) if err != nil { return err } @@ -642,62 +655,35 @@ func genPassPair() (string, string) { return string(username), string(password) } -func chKey(channel *m.Channel) string { - return fmt.Sprintf("channel:%d", channel.ID) -} - -func cache(ctx context.Context, channels []*m.Channel) error { - if len(channels) == 0 { - return nil +func chAuthItems(channel *m.Channel, whitelists *[]string) []string { + var count = 1 + var ips = make([]string, 0) + if channel.AuthIP && whitelists != nil { + count = len(*whitelists) + ips = *whitelists } - pipe := g.Redis.TxPipeline() - - zList := make([]redis.Z, 0, len(channels)) - for _, channel := range channels { - marshal, err := json.Marshal(channel) - if err != nil { - return err + var proxy = channel.ProxyHost + ":" + strconv.Itoa(int(channel.ProxyPort)) + var sb = strings.Builder{} + var items = make([]string, count) + for i := range items { + // 权限 key 格式:::?:?:? + sb.WriteString(proxy) + if channel.AuthIP { + sb.WriteString(":" + ips[i]) + } + if channel.AuthPass { + sb.WriteString(":" + channel.Username + ":" + channel.Password) } - expiration := time.Time(channel.Expiration) - pipe.Set(ctx, chKey(channel), string(marshal), time.Until(expiration)) - zList = append(zList, redis.Z{ - Score: float64(expiration.Unix()), - Member: channel.ID, - }) - } - pipe.ZAdd(ctx, "tasks:channel", zList...) - - _, err := pipe.Exec(ctx) - if err != nil { - return err } - return nil -} - -func deleteCache(ctx context.Context, channels []*m.Channel) error { - if len(channels) == 0 { - return nil - } - - keys := make([]string, len(channels)) - for i := range channels { - keys[i] = chKey(channels[i]) - } - _, err := g.Redis.Del(ctx, keys...).Result() - if err != nil { - return err - } - - return nil + return items } type ChannelAuthType int const ( - ChannelAuthTypeAll ChannelAuthType = iota - ChannelAuthTypeIp + ChannelAuthTypeIp ChannelAuthType = iota + 1 ChannelAuthTypePass )