统一访问管理中心--UAM (Unify Access Management Center)
UAM是基于RBCA模型的统一用户权限管理中心,支持任意需要进行访问控制的系统来接入,支持Rest API及RPC接入。
本项目包含多个服务,包括"UAM-后台管理-后端"、"UAM-API服务"、"UAM-RPC服务"、"UAM-Job任务调度服务", UAM-后台管理-前端项目在这里
技术栈:go-zero、gorm、Mysql、Redis、Kafka、etcd
系统提供了一个后台管理平台,UAM管理员和各应用管理员可登录后台对各种资源实体进行CRUD操作。
应用接入后会获得app_id和app_secret,按照接入规范即可访问Rest API服务获取权限相关资源,从而实现访问控制。
UAM-Admin及Rest API均通过调用RPC Service实现对数据层的操作,通过etcd实现服务注册、发现。
对于一些异步操作,通过基于Kafka实现的异步任务队列在Task Worker中异步执行,另外定时任务类需求可通过Cron Job来配置执行。
目前UAM-Admin提供了一套简单的登录注册模块来实现用户添加,后续可同步企业内部用户表替换现有用户表,可接入OAuth认证方式替换账号密码登录。
当前登录用户是通过JWT实现认证,通过redis缓存实现JWT Token续期,避免Token过期造成用户体验问题。
假设应用App01需要接入UAM系统,App01管理员需要向UAM系统管理员提交接入申请,
申请通过后UAM系统管理员在UAM后台添加客户端接入记录,并将系统生成的app_id和app_secret发给App01管理员,
并授予App01管理员在UAM后台操作App01资源的权限。
后续App01管理员也可登录UAM后台对App01系统下的资源实体进行CURD操作和用户访问权限管理,
App01开发人员通过app_id和app_secret即可访问UAM开放的Rest API服务获取App01下的资源数据和用户权限数据,
以实现访问控制管理。
自行搭建以下组件
-
Mysql
-
Redis
-
etcd
-
Kafka
-
创建
uam数据库 -
创建所需表:deploy/sql/*.sql
# 更新services/job/etc/uam-job.yaml配置文件 cd services/job go run job.go
# 更新services/rpc/etc/uamrpc.yaml配置文件 cd services/rpc go run uamrpc.go
# 更新services/api/etc/uam-api.yaml配置文件 cd services/api go run uam.go
# 更新services/admin/etc/uam-admin-api.yaml配置文件 cd services/admin go run uam-admin.go
-
进入admin目录
cd services/admin -
创建新接口依赖的类型api文件
mkdir desc/role vim desc/role/role.api
-
定义接口依赖的类型
syntax = "v1" info( title: "角色管理" desc: "角色管理" author: "will515" email: "wuyuw515@gmail.com" version: 1.0 ) // 获取所有角色 type ( Role { Id int64 `json:"id"` ClientId int64 `json:"client_id"` Name string `json:"name"` Desc string `json:"desc"` Editable int64 `json:"editable"` CreateTime string `json:"create_time"` UpdateTime string `json:"update_time"` Permissions []string `json:"permissions"` } RoleListReq { ClientId int64 `form:"client_id"` Editable string `form:"editable,optional"` } RoleListResp { List []Role `json:"list"` } )
-
在desc/admin.api文件中导入刚创建的类型文件,并定义接口
import ( # "core/core.api" # "user/user.api" # "client/client.api" # "permission/permission.api" # 导入类型文件 "role/role.api" # "group/group.api" ) # 定义接口 @server( prefix: "/uam/admin/v1" group: role middleware: JwtAuth, AccessControl ) service uam-admin-api { @doc "获取角色列表" @handler RoleList get /roles (RoleListReq) returns (RoleListResp) }
-
使用命令行工具goctl生成代码模板
# 在uam/services/admin目录下执行 goctl api go -api desc/admin.api --dir .
-
修改生成的handler和logic目录下对应的包
-
创建表对应的包
mkdir model/user
-
分别创建model/user/gorm.go和model/user/model.go两个文件,定义orm结构体和封装数据库操作的model
gorm.go
package user import "time" const TableUser = "user" type User struct { Id int64 `gorm:"column:id;primaryKey;autoIncrement"` Uid int64 `gorm:"column:uid"` // uid Nickname string `gorm:"column:nickname"` // 花名 Email string `gorm:"column:email"` // 邮箱 Phone string `gorm:"column:phone"` // 手机 CreateTime time.Time `gorm:"column:create_time"` UpdateTime time.Time `gorm:"column:update_time"` } func (User) TableName() string { return TableUser }
model.go
package user import ( "context" "fmt" "uam/services/model" "gorm.io/gorm" ) type UserModel struct { table string db *gorm.DB } func NewUserModel(db *gorm.DB) *UserModel { return &UserModel{ db: db, table: TableUser, } } // FindOneByUid 根据uid查询用户信息 func (m *UserModel) FindOneByUid(ctx context.Context, uid int64) (*User, error) { var ( err error user User ) db := m.db.Table(m.table) err = db.Where("`uid` = ?", uid).First(&user).Error switch err { case nil: return &user, nil case gorm.ErrRecordNotFound: return nil, model.ErrNotFound default: return nil, err } }
-
更新proto文件,定义类型和接口
services/rpc/uamprc.proto
// 获取用户信息 message GetUserInfoReq { int64 uid = 1; } message GetUserInfoResp { int64 uid = 1; string nickname = 2; string email = 3; string phone = 4; } // services service Uam { // 定义接口 rpc getUserInfo(GetUserInfoReq) returns(GetUserInfoResp); }
-
生成rpc服务代码
goctl rpc protoc uamrpc.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
-
添加RPC接口业务逻辑
-
Fork 代码仓库
-
在仓库导航栏的
Settings->Secrets and variables->Actions->New repository secret添加 Docker Hub 个人账户的账户名和密码账户变量名:
DOCKERHUB_TOKEN密码变量名:
DOCKERHUB_USERNAME -
拉取代码
$ git clone git@github.com:${usename}/uam.git -
打 tag,CI会根据tag的前缀构建对应服务的docker镜像并上传到Docker Hub
$ git tag admin-0.0.1 $ git tag rpc-0.0.1 $ git tag job-0.0.1 $ git tag api-0.0.1 $ git push origin admin-0.0.1
-
点击仓库导航栏的
Actions选项卡查看 Workflow 执行情况 -
在 Docker Hub 仓库中确认镜像是否上传成功