diff --git a/devcloud/mcenter/README.md b/devcloud/mcenter/README.md index e641b0f..a551478 100644 --- a/devcloud/mcenter/README.md +++ b/devcloud/mcenter/README.md @@ -10,3 +10,18 @@ 鉴权: 你能干什么(范围) + +## 概要设计 + +针对问题(需求),给出一种解决方案(解题) + +![](./design.drawio) + +## 详细设计 + +定义业务 + + + + + diff --git a/devcloud/mcenter/apps/token/README.md b/devcloud/mcenter/apps/token/README.md index c6984e6..b885cc7 100644 --- a/devcloud/mcenter/apps/token/README.md +++ b/devcloud/mcenter/apps/token/README.md @@ -1,2 +1,20 @@ # 令牌管理 ++ 颁发访问令牌: Login ++ 撤销访问令牌: 令牌失效了 Logout ++ 校验访问令牌:检查令牌的合法性, 是不是伪造的 + +## 详情设计的时候 + +字段(业务需求) + +令牌: ++ 过期时间 ++ 颁发时间 ++ 被颁发的人 ++ ... + + +问题: 无刷新功能, 令牌到期了,自动退出了, 过期时间设置长一点, 长时间不过期 又有安全问题 +1. 业务功能: 令牌的刷新, 令牌过期了过后,允许用户进行刷新(需要使用刷新Token来刷新, 刷新Token也是需要有过期时间, 这个时间决定回话长度),有了刷新token用户不会出现 使用中被中断的情况, 并且长时间未使用,系统也户自动退出(刷新Token过期) + diff --git a/devcloud/mcenter/apps/token/docs/refresh.drawio b/devcloud/mcenter/apps/token/docs/refresh.drawio new file mode 100644 index 0000000..e69de29 diff --git a/devcloud/mcenter/apps/token/enum.go b/devcloud/mcenter/apps/token/enum.go new file mode 100644 index 0000000..dd2ce47 --- /dev/null +++ b/devcloud/mcenter/apps/token/enum.go @@ -0,0 +1,31 @@ +package token + +type SOURCE int + +const ( + // 未知 + SOURCE_UNKNOWN SOURCE = iota + // Web + SOURCE_WEB + // IOS + SOURCE_IOS + // ANDROID + SOURCE_ANDROID + // PC + SOURCE_PC + // API 调用 + SOURCE_API SOURCE = 10 +) + +type LOCK_TYPE int + +const ( + // 用户退出登录 + LOCK_TYPE_REVOLK LOCK_TYPE = iota + // 刷新Token过期, 回话中断 + LOCK_TYPE_TOKEN_EXPIRED + // 异地登陆 + LOCK_TYPE_OTHER_PLACE_LOGGED_IN + // 异常Ip登陆 + LOCK_TYPE_OTHER_IP_LOGGED_IN +) diff --git a/devcloud/mcenter/apps/token/interfaceg.go b/devcloud/mcenter/apps/token/interfaceg.go new file mode 100644 index 0000000..aedc9dd --- /dev/null +++ b/devcloud/mcenter/apps/token/interfaceg.go @@ -0,0 +1,70 @@ +package token + +import ( + "context" + "time" +) + +type Service interface { + // 颁发访问令牌: Login + IssueToken(context.Context, *IssueTokenRequest) (*Token, error) + // 撤销访问令牌: 令牌失效了 Logout + RevolkToken(context.Context, *RevolkTokenRequest) (*Token, error) + + // 校验访问令牌:检查令牌的合法性, 是不是伪造的 + ValidateToken(context.Context, *ValidateTokenRequest) (*Token, error) +} + +// 用户会给我们 用户的身份凭证,用于换取Token +type IssueTokenRequest struct { + // 端类型 + Source SOURCE `json:"source"` + // 认证方式 + Issuer string `json:"issuer"` + // 参数 + Parameter IssueParameter `json:"parameter"` +} + +type IssueParameter map[string]any + +/* +password issuer parameter +*/ + +func (p IssueParameter) Username() string { + return GetIssueParameterValue[string](p, "username") +} + +func (p IssueParameter) Password() string { + return GetIssueParameterValue[string](p, "password") +} + +func (p IssueParameter) SetUsername(v string) { + p["username"] = v +} + +func (p IssueParameter) SetPassword(v string) { + p["password"] = v +} + +/* +private token issuer parameter +*/ + +func (p IssueParameter) AccessToken() string { + return GetIssueParameterValue[string](p, "access_token") +} + +func (p IssueParameter) ExpireTTL() time.Duration { + return time.Second * time.Duration(GetIssueParameterValue[int64](p, "expired_ttl")) +} + +func (p IssueParameter) SetAccessToken(v string) { + p["access_token"] = v +} + +type RevolkTokenRequest struct { +} + +type ValidateTokenRequest struct { +} diff --git a/devcloud/mcenter/apps/token/model.go b/devcloud/mcenter/apps/token/model.go new file mode 100644 index 0000000..28c454e --- /dev/null +++ b/devcloud/mcenter/apps/token/model.go @@ -0,0 +1,67 @@ +package token + +import "time" + +// 需要存储到数据库里面的对象(表) + +type Token struct { + // 在添加数据需要, 主键 + Id uint64 `json:"id" gorm:"column:id;type:uint;primary_key;"` + // 用户来源 + Source SOURCE `json:"source" gorm:"column:source;type:tinyint(1);index" description:"用户来源"` + // 颁发器, 办法方式(user/pass ) + Issuer string `json:"issuer" gorm:"column:issuer;type:varchar(100);index" description:"颁发器"` + // 该Token属于哪个用户 + UserId uint64 `json:"user_id" gorm:"column:user_id;index" description:"持有该Token的用户Id"` + // 用户名 + UserName string `json:"user_name" gorm:"column:user_name;type:varchar(100);not null;index" description:"持有该Token的用户名称"` + // 是不是管理员 + IsAdmin bool `json:"is_admin" gorm:"column:is_admin;type:tinyint(1)" description:"是不是管理员"` + // 令牌生效空间Id + NamespaceId uint64 `json:"namespace_id" gorm:"column:namespace_id;type:uint;index" description:"令牌所属空间Id"` + // 令牌生效空间名称 + NamespaceName string `json:"namespace_name" gorm:"column:namespace_name;type:varchar(100);index" description:"令牌所属空间"` + // 访问范围定义, 鉴权完成后补充 + Scope map[string]string `json:"scope" gorm:"column:scope;type:varchar(100);serializer:json" description:"令牌访问范围定义"` + // 颁发给用户的访问令牌(用户需要携带Token来访问接口) + AccessToken string `json:"access_token" gorm:"column:access_token;type:varchar(100);not null;uniqueIndex" description:"访问令牌"` + // 访问令牌过期时间 + AccessTokenExpiredAt *time.Time `json:"access_token_expired_at" gorm:"column:access_token_expired_at;type:timestamp;index" description:"访问令牌的过期时间"` + // 刷新Token + RefreshToken string `json:"refresh_token" gorm:"column:refresh_token;type:varchar(100);not null;uniqueIndex" description:"刷新令牌"` + // 刷新Token过期时间 + RefreshTokenExpiredAt *time.Time `json:"refresh_token_expired_at" gorm:"column:refresh_token_expired_at;type:timestamp;index" description:"刷新令牌的过期时间"` + // 创建时间 + IssueAt time.Time `json:"issue_at" gorm:"column:issue_at;type:timestamp;default:current_timestamp;not null;index" description:"令牌颁发时间"` + // 更新时间 + RefreshAt *time.Time `json:"refresh_at" gorm:"column:refresh_at;type:timestamp" description:"令牌刷新时间"` + // 令牌状态 + Status *Status `json:"status" gorm:"embedded" modelDescription:"令牌状态"` + // 其他扩展信息 + Extras map[string]string `json:"extras" gorm:"column:extras;serializer:json;type:json" description:"其他扩展信息"` +} + +func NewStatus() *Status { + return &Status{} +} + +type Status struct { + // 冻结时间 + LockAt *time.Time `json:"lock_at" bson:"lock_at" gorm:"column:lock_at;type:timestamp;index" description:"冻结时间"` + // 冻结类型 + LockType LOCK_TYPE `json:"lock_type" bson:"lock_type" gorm:"column:lock_type;type:tinyint(1)" description:"冻结类型 0:用户退出登录, 1:刷新Token过期, 回话中断, 2:异地登陆, 异常Ip登陆" enum:"0|1|2|3"` + // 冻结原因 + LockReason string `json:"lock_reason" bson:"lock_reason" gorm:"column:lock_reason;type:text" description:"冻结原因"` +} + +func (s *Status) SetLockAt(v time.Time) { + s.LockAt = &v +} + +func (s *Status) ToMap() map[string]any { + return map[string]any{ + "lock_at": s.LockAt, + "lock_type": s.LockType, + "lock_reason": s.LockReason, + } +} diff --git a/devcloud/mcenter/apps/token/tools.go b/devcloud/mcenter/apps/token/tools.go new file mode 100644 index 0000000..f8bb85b --- /dev/null +++ b/devcloud/mcenter/apps/token/tools.go @@ -0,0 +1,13 @@ +package token + +// 泛型函数 +func GetIssueParameterValue[T any](p IssueParameter, key string) T { + v := p[key] + if v != nil { + if value, ok := v.(T); ok { + return value + } + } + var zero T + return zero +} diff --git a/devcloud/mcenter/design.drawio b/devcloud/mcenter/design.drawio index dce90eb..72c63ea 100644 --- a/devcloud/mcenter/design.drawio +++ b/devcloud/mcenter/design.drawio @@ -1,144 +1,159 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + + + + + + + + + + + + + + + + diff --git a/devcloud/ui.drawio b/devcloud/ui.drawio index e69de29..95914de 100644 --- a/devcloud/ui.drawio +++ b/devcloud/ui.drawio @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Go 语言大型项目开发必备技能之Ioc.pptx b/docs/Go 语言大型项目开发必备技能之Ioc.pptx new file mode 100644 index 0000000..45044ae Binary files /dev/null and b/docs/Go 语言大型项目开发必备技能之Ioc.pptx differ diff --git a/skills/ioc/map.go b/skills/ioc/map.go index 8c4f483..253f020 100644 --- a/skills/ioc/map.go +++ b/skills/ioc/map.go @@ -27,6 +27,8 @@ func (m *MapContainer) Get(name string) Object { } // 初始化所有已经注册的对象 +// yaml, toml map[key]obj +// [object_name] func (m *MapContainer) Init() error { for _, v := range m.storage { if err := v.Init(); err != nil {