From edec734b71f35013e4bb9c81d677ac11d80518fc Mon Sep 17 00:00:00 2001 From: luorijun Date: Fri, 28 Mar 2025 15:01:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=99=BB=E5=BD=95=E4=B8=8E?= =?UTF-8?q?=E9=89=B4=E6=9D=83=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/fill/main.go | 86 ++++++++++++++++++++++++--------------- scripts/sql/init.sql | 4 +- test/test-api.http | 5 +++ web/auth.go | 47 +++++++++++++++++++++ web/handlers/client.go | 52 ----------------------- web/handlers/login.go | 13 ++++-- web/models/client.gen.go | 2 +- web/queries/client.gen.go | 8 ++-- web/router.go | 8 +--- web/services/auth.go | 3 +- web/services/session.go | 12 +++--- 11 files changed, 132 insertions(+), 108 deletions(-) create mode 100644 test/test-api.http delete mode 100644 web/handlers/client.go diff --git a/cmd/fill/main.go b/cmd/fill/main.go index ceed466..17cdf41 100644 --- a/cmd/fill/main.go +++ b/cmd/fill/main.go @@ -7,6 +7,8 @@ import ( "platform/pkg/orm" "platform/web/models" q "platform/web/queries" + + "golang.org/x/crypto/bcrypt" ) func main() { @@ -14,41 +16,59 @@ func main() { logs.Init() orm.Init() - q.User.Select( - q.User.Phone, - ).Create(&models.User{ - Phone: "12312341234", - }) + q.User. + Select( + q.User.Phone). + Create(&models.User{ + Phone: "12312341234"}) - q.Proxy.Select( - q.Proxy.Version, - q.Proxy.Name, - q.Proxy.Host, - q.Proxy.Type, - ).Create(&models.Proxy{ - Version: 1, - Name: "7a17e8b4-cdc3-4500-bf16-4a665991a7f6", - Host: "110.40.82.248", - Type: 1, - }) + q.Proxy. + Select( + q.Proxy.Version, + q.Proxy.Name, + q.Proxy.Host, + q.Proxy.Type). + Create(&models.Proxy{ + Version: 1, + Name: "7a17e8b4-cdc3-4500-bf16-4a665991a7f6", + Host: "110.40.82.248", + Type: 1}) - q.Node.Select( - q.Node.Version, - q.Node.Name, - q.Node.Host, - q.Node.Isp, - q.Node.Prov, - q.Node.City, - q.Node.Status, - ).Create(&models.Node{ - Version: 1, - Name: "test-node", - Host: "123", - Isp: "test-isp", - Prov: "test-prov", - City: "test-city", - Status: 1, - }) + q.Node. + Select( + q.Node.Version, + q.Node.Name, + q.Node.Host, + q.Node.Isp, + q.Node.Prov, + q.Node.City, + q.Node.Status). + Create(&models.Node{ + Version: 1, + Name: "test-node", + Host: "123", + Isp: "test-isp", + Prov: "test-prov", + City: "test-city", + Status: 1}) + + var secret, _ = bcrypt.GenerateFromPassword([]byte("test"), bcrypt.DefaultCost) + q.Client. + Select( + q.Client.ClientID, + q.Client.ClientSecret, + q.Client.GrantClient, + q.Client.GrantRefresh, + q.Client.Spec, + q.Client.Name). + Create(&models.Client{ + ClientID: "test", + ClientSecret: string(secret), + GrantClient: true, + GrantRefresh: true, + Spec: 0, + Name: "默认客户端", + }) slog.Info("✔ Data inserted successfully") } diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index 08bebe2..1806b70 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -184,7 +184,7 @@ create table client ( grant_refresh bool not null default false, spec int not null, name varchar(255) not null, - version int not null, + icon varchar(255), status int not null default 1, created_at timestamp default current_timestamp, updated_at timestamp default current_timestamp, @@ -206,7 +206,7 @@ comment on column client.grant_client is '允许客户端凭证授予'; comment on column client.grant_refresh is '允许刷新令牌授予'; comment on column client.spec is '安全规范:0-web,1-native,2-browser'; comment on column client.name is '名称'; -comment on column client.version is '版本'; +comment on column client.icon is '图标URL'; comment on column client.status is '状态:1-正常,0-禁用'; comment on column client.created_at is '创建时间'; comment on column client.updated_at is '更新时间'; diff --git a/test/test-api.http b/test/test-api.http new file mode 100644 index 0000000..ba567a6 --- /dev/null +++ b/test/test-api.http @@ -0,0 +1,5 @@ +GET http://api:123456@110.40.82.248:9990/port/active +Accept: application/json + +### + diff --git a/web/auth.go b/web/auth.go index a2bc900..c1bbc24 100644 --- a/web/auth.go +++ b/web/auth.go @@ -56,3 +56,50 @@ func PermitUser(permissions ...string) fiber.Handler { return c.Next() } } + +func PermitDevice(permissions ...string) fiber.Handler { + return func(c *fiber.Ctx) error { + // 获取令牌 + var header = c.Get("Authorization") + var token = strings.TrimPrefix(header, "Bearer ") + if token == "" { + return c.Status(fiber.StatusUnauthorized).JSON(common.ErrResp{ + Error: true, + Message: "没有权限", + }) + } + + // 验证令牌 + auth, err := services.Session.Find(c.Context(), token) + if err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(common.ErrResp{ + Error: true, + Message: "没有权限", + }) + } + + // 检查权限 + switch auth.Payload.Type { + case services.PayloadAdmin: + // 管理员不需要权限检查 + case services.PayloadClientPublic, services.PayloadClientConfidential: + if len(permissions) > 0 && !auth.AnyPermission(permissions...) { + return c.Status(fiber.StatusForbidden).JSON(common.ErrResp{ + Error: true, + Message: "拒绝访问", + }) + } + default: + return c.Status(fiber.StatusForbidden).JSON(common.ErrResp{ + Error: true, + Message: "拒绝访问", + }) + } + + // 将认证信息存储在上下文中 + c.Locals("auth", auth) + c.Locals("access_token", token) // 存储原始令牌,便于后续操作 + + return c.Next() + } +} diff --git a/web/handlers/client.go b/web/handlers/client.go deleted file mode 100644 index d527f24..0000000 --- a/web/handlers/client.go +++ /dev/null @@ -1,52 +0,0 @@ -package handlers - -import ( - "platform/web/models" - q "platform/web/queries" - "time" - - "github.com/gofiber/fiber/v2" - "golang.org/x/crypto/bcrypt" -) - -type CreateClientReq struct { - ClientID string `query:"client_id"` - ClientSecret string `query:"client_secret"` -} - -func CreateClient(c *fiber.Ctx) error { - // 验证请求参数 - req := new(CreateClientReq) - if err := c.QueryParser(req); err != nil { - return err - } - if req.ClientID == "" { - return fiber.NewError(fiber.StatusBadRequest, "client_id不能为空") - } - if req.ClientSecret == "" { - return fiber.NewError(fiber.StatusBadRequest, "client_secret不能为空") - } - - // 创建客户端 - hashedSecret, err := bcrypt.GenerateFromPassword([]byte(req.ClientSecret), bcrypt.DefaultCost) - if err != nil { - return err - } - client := &models.Client{ - ClientID: req.ClientID, - ClientSecret: string(hashedSecret), - Name: "默认客户端 - " + time.Now().String(), - Spec: 0, - GrantCode: true, - GrantClient: true, - GrantRefresh: true, - Version: 0, - } - - err = q.Client.Create(client) - if err != nil { - return err - } - - return c.JSON(client) -} diff --git a/web/handlers/login.go b/web/handlers/login.go index 32f722b..80e6e31 100644 --- a/web/handlers/login.go +++ b/web/handlers/login.go @@ -18,8 +18,9 @@ type LoginReq struct { } type LoginResp struct { - Token string `json:"token"` - Expires int64 `json:"expires"` + Token string `json:"token"` + Expires int64 `json:"expires"` + Auth services.AuthContext `json:"auth"` } func Login(c *fiber.Ctx) error { @@ -65,6 +66,7 @@ func loginByPhone(c *fiber.Ctx, req *LoginReq) error { if user == nil { user = &models.User{ Phone: req.Username, + Name: req.Username, } } @@ -87,8 +89,10 @@ func loginByPhone(c *fiber.Ctx, req *LoginReq) error { "user": {}, }, Payload: services.Payload{ - Type: services.PayloadUser, - Id: user.ID, + Id: user.ID, + Type: services.PayloadUser, + Name: user.Name, + Avatar: user.Avatar, }, } duration := time.Hour * 24 @@ -103,5 +107,6 @@ func loginByPhone(c *fiber.Ctx, req *LoginReq) error { return c.JSON(LoginResp{ Token: token.AccessToken, Expires: token.AccessTokenExpires.Unix(), + Auth: auth, }) } diff --git a/web/models/client.gen.go b/web/models/client.gen.go index 8f729cb..0e22df1 100644 --- a/web/models/client.gen.go +++ b/web/models/client.gen.go @@ -23,7 +23,7 @@ type Client struct { GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予 Spec int32 `gorm:"column:spec;not null;comment:安全规范:0-web,1-native,2-browser" json:"spec"` // 安全规范:0-web,1-native,2-browser Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称 - Version int32 `gorm:"column:version;not null;comment:版本" json:"version"` // 版本 + Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL Status int32 `gorm:"column:status;not null;default:1;comment:状态:1-正常,0-禁用" json:"status"` // 状态:1-正常,0-禁用 CreatedAt time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 UpdatedAt time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 diff --git a/web/queries/client.gen.go b/web/queries/client.gen.go index 10dc2a3..e311a23 100644 --- a/web/queries/client.gen.go +++ b/web/queries/client.gen.go @@ -36,7 +36,7 @@ func newClient(db *gorm.DB, opts ...gen.DOOption) client { _client.GrantRefresh = field.NewBool(tableName, "grant_refresh") _client.Spec = field.NewInt32(tableName, "spec") _client.Name = field.NewString(tableName, "name") - _client.Version = field.NewInt32(tableName, "version") + _client.Icon = field.NewString(tableName, "icon") _client.Status = field.NewInt32(tableName, "status") _client.CreatedAt = field.NewTime(tableName, "created_at") _client.UpdatedAt = field.NewTime(tableName, "updated_at") @@ -60,7 +60,7 @@ type client struct { GrantRefresh field.Bool // 允许刷新令牌授予 Spec field.Int32 // 安全规范:0-web,1-native,2-browser Name field.String // 名称 - Version field.Int32 // 版本 + Icon field.String // 图标URL Status field.Int32 // 状态:1-正常,0-禁用 CreatedAt field.Time // 创建时间 UpdatedAt field.Time // 更新时间 @@ -90,7 +90,7 @@ func (c *client) updateTableName(table string) *client { c.GrantRefresh = field.NewBool(table, "grant_refresh") c.Spec = field.NewInt32(table, "spec") c.Name = field.NewString(table, "name") - c.Version = field.NewInt32(table, "version") + c.Icon = field.NewString(table, "icon") c.Status = field.NewInt32(table, "status") c.CreatedAt = field.NewTime(table, "created_at") c.UpdatedAt = field.NewTime(table, "updated_at") @@ -121,7 +121,7 @@ func (c *client) fillFieldMap() { c.fieldMap["grant_refresh"] = c.GrantRefresh c.fieldMap["spec"] = c.Spec c.fieldMap["name"] = c.Name - c.fieldMap["version"] = c.Version + c.fieldMap["icon"] = c.Icon c.fieldMap["status"] = c.Status c.fieldMap["created_at"] = c.CreatedAt c.fieldMap["updated_at"] = c.UpdatedAt diff --git a/web/router.go b/web/router.go index 6549253..789bf87 100644 --- a/web/router.go +++ b/web/router.go @@ -11,14 +11,10 @@ func ApplyRouters(app *fiber.App) { // 认证 auth := api.Group("/auth") - auth.Post("/verify/sms", PermitUser(), handlers.SmsCode) - auth.Post("/login/sms", PermitUser(), handlers.Login) + auth.Post("/verify/sms", PermitDevice(), handlers.SmsCode) + auth.Post("/login/sms", PermitDevice(), handlers.Login) auth.Post("/token", handlers.Token) - // 客户端 - client := api.Group("/client") - client.Get("/test/create", handlers.CreateClient) - // 通道 channel := api.Group("/channel", PermitUser()) channel.Post("/create", handlers.CreateChannel) diff --git a/web/services/auth.go b/web/services/auth.go index 274005c..8f41190 100644 --- a/web/services/auth.go +++ b/web/services/auth.go @@ -59,8 +59,9 @@ func (s *authService) OauthClientCredentials(ctx context.Context, client *models auth := AuthContext{ Permissions: permissions, Payload: Payload{ - Type: clientType, Id: client.ID, + Type: clientType, + Name: client.Name, }, } diff --git a/web/services/session.go b/web/services/session.go index 222288d..5f9852e 100644 --- a/web/services/session.go +++ b/web/services/session.go @@ -238,15 +238,17 @@ func mergeConfig(defaultCfg SessionConfig, customCfg SessionConfig) SessionConfi // AuthContext 定义认证信息 type AuthContext struct { - Payload Payload - Permissions map[string]struct{} - Metadata map[string]interface{} + Payload Payload `json:"payload"` + Permissions map[string]struct{} `json:"permissions,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` } // Payload 定义负载信息 type Payload struct { - Type PayloadType - Id int32 + Id int32 `json:"id,omitempty"` + Type PayloadType `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Avatar string `json:"avatar,omitempty"` } // PayloadType 定义负载类型