[TOC]
一般来说,路径会是类似于 /api/sso/user/user/:id 这样的结构,但是为了与其他模块的结合以及做反向代理流量分发,需要扩展路径前缀。比如路径会改成 /api/sso/yyapi/user/user/:id,这里 api 路径从 /api变成了 /api/sso/yyapi,这里就是路径前缀。
为了方便前端用户统一管理 userandrole 相关的api,这里就变成了 host/api_prefix + uri 的形式,方便统一管理。
管理员 指的是拥有相关角色的用户。
部分接口需要验证权限,需要在 header 设置 key 是 token,值是 token value 的数据,比如
setHeader("token", "someValue")
同一个登录方式只能同时在一个平台上有效登录,不支持同一个登录方式在多个平台登录。
值 | 意义 |
---|---|
H5 | 手机浏览器登录 |
PC | 电脑浏览器登录 |
ANDROID | 安卓手机 |
IOS | 苹果手机 |
XIAOCHENGXU | 微信小程序 |
值 | 意义 |
---|---|
IDPASSWD | 账户密码登录 |
邮件验证 | |
PHONE | 手机号验证码验证 |
微信授权 | |
qq 授权 |
值(整数) | 意义 |
---|---|
0 | token 错误/无效(401) |
1 | token正确,但无相关操作权限(403) |
2 | token 正确,但是采用账户密码登录方式,密码被初始化了,需要修改密码才能使用其他功能 |
9 | 验证成功,token有效,有对应的权限 |
// POST /api/sso/user/idpasswd
// roleIds 中的值为调用接口用户所包含的角色列表和 childrenRole 列表值
{
"loginId": "testuser",
"passwd": "abc123",
"avatar": "http://some.com/avatar.jpg",
"roleIds": ["aaaa", "bbbb", "cccc"]
}
// 注意这种方式创建的账户,下次登录时,需要修改密码
// POST /api/sso/user/idpasswd/changepasswd
{
"passwd": "some new passwd"
}
// 首先请求短信发送接口,发送短信验证码
// 然后调用本接口进行短信验证
// 调用本接口的前置条件是已经使用微信授权进行了登录
// 关于账户合并的一些规则
// 如果 phone 不存在,则把 phone 信息追加到当前账户体系下
// 如果 phone 存在,以 phone 为主,修改 wechatAuth 的 userid
// 标记原 user 数据为被合并的数据,标记为失效
// 所以,如果想要做绑定操作,并且有资源关联,那么最好的是拉起微信授权后,立刻绑定手机号
// 调用者获取到成功响应后,就应该重新拉去登录,因为之前的信息会被删除
// POST /api/sso/user/wx/bindphone
{
"phone": "13812345678",
"code": "123456"
}
// GET /api/sso/user/me
// POST/GET /api/sso/user/logout
// 需要在登录状态下调用此接口
// POST /api/sso/user/phone
{
"phone": "13812345678",
"avatar": "http://some.com/avatar.jpg",
"roleIds": ["aaaa", "bbbb", "cccc"]
}
// POST /api/sso/user/ban
// t 指的是封禁到期时间,精确到秒的时间戳
{
"userId": "userid",
"reason": "违反xxx规则",
"t": 1571366536
}
// POST /api/sso/user/unban
{
"userId": "userid",
"reason": "解封理由"
}
// POST /api/sso/user/idpasswd/resetpasswd
// 注意这里和用户自己修改密码的区别
{
"userId": "userId"
}
// GET /api/sso/user/user/:id
// 路径最后是要读取的用户的 id
// GET /api/sso/user/wx/openid/:id
// 路径中的 id 指的是 openid
// GET /api/sso/user/phone/:id
// 路径中的 id 指的是 phone 号码
// GET /api/sso/user/loginhistory/:id?page=1
// 路径中的 id 指的是用户 id,page 指的是读取第几页的数据
// 单页返回记录为 10 条数据,返回数据中无 total 字段,根据返回的数据是否为空(或是否size==10)来判断是否读取完毕
// GET /api/sso/user/users
// 支持的 url 参数如下
// loginid - 登录id,支持部分匹配
// phone - 支持部分匹配
// nickname - 微信登录方式的 nickname,支持部分匹配
// 上述三个参数,只能同时一个生效
// page - 分页参数,从 1 开始
// size - 单页条数,默认 10
// GET /api/sso/user/wx/appid?platform=H5
// platform 可选值 H5 / APP / XIAOCHENGXU
// POST /api/sso/user/idpasswd/login
// platform 可选值 H5 / PC / ANDROID / IOS
{
"loginId": "testauser",
"passwd": "abc123456",
"platform": "H5"
}
// 登录成功后,返回的用户信息中,如果 init 字段为 true,那么需要提示用户进行密码修改
// POST /api/sso/user/wx/login
// platform 可选值 H5 - 网页拉起微信授权 / APP - app 微信授权方式 // XIAOCHENGXU - 微信小程序
{
"code": "wechat code....",
"platform": "H5"
}
// 小程序登录分为两个步骤
// 1. 调用小程序登录接口,根据调用情况有三种情况
// 1.1 全新用户,需要进一步传递 profile 信息才能使用
// 1.2 用户存在,但是没有更新 profile信息,需要更新才能使用
// 2.3 用户存在,profile 信息完整,可以使用
// 根据 code 换取登录
// POST /api/sso/user/wx/xcxlogin
{
"code": "xxxx"
}
// 调用成功结果为 http status code,需要根据 body 中的 code 判断是否传递 profile 信息
// 1. body 中的 code 为 2000,需要进一步传递 profile 信息,见下面描述的接口
// 2. body 中的 code 为 200,登录成功
// 传递 profile 信息
// 调用本接口,需要在 header 设置 token,token 从上一步获取
// POST /api/sso/user/wx/xcxprofile
{
"nickname": "xxx",
"sex": 0,
"avatar": "https://xxxx",
"city": "xxx",
"province": "xxx",
"country": "xxxx"
}
// 手机号注册登录分为两个步骤
// 1、获取验证码
// 2、验证验证码有效性
// 如果用户未注册过,验证通过后注册账户
// 1、发送短信验证码
// POST /api/sso/user/phone/sendsms
// 如果运行在 debug 模式,不会真发送短信,同时会返回 code
// 否则会真实发送短信验证码,仅返回发送成功的提示给调用者
{
"phone": "13812345678"
}
// 2、验证验证码有效性(及同步创建账户,如果不存在的话)
// POST /api/sso/user/phone/checksms
{
"phone": "13812345678",
"code": "123456",
"platform": "H5"
}
// POST /api/sso/user/token/check
{
"token": "some token value"
}
// 返回数据中,根据 valid 字段判断 token 是否有效,true - 有效,false - 无效,无效时,reason 可能有值
// 有效时,同步返回用户信息和角色信息
// POST /api/sso/user/auth
// 本接口是提供给调用者一种验证机制,验证token对应的用户有无某接口权限
{
"token": "some token value",
"method": "GET",
"path": "/api/sso/course/info/abcdefghi"
}
// 返回的数据包含了三部分,指示了 token 是否有效,用户是否具有权限
// 如果验证成功,权限有效,同步返回用户信息和 role 信息
###角色(role)接口
角色由三部分组成,分别是 item、permission、role
- item 中定义了具体的api的 method、path,页面的 menu、button 等信息
- permission 是多个 item 组合起来的一个容器,也有自己的 menu\button 信息
- role 是多个 permission 组合起来的容器,也有自己的 menu\button 信息
path 支持一个通配符 *
,比如接口为 /api/sso/user/:id
,配置时,就可以写成 /api/sso/user/*
即可。
// POST /api/sso/role/item
// name/method/path 为必输字段
// name 字段不可重复
{
"name": "读取用户明细",
"method": "GET",
"path": "/api/sso/user/*",
"resource": "",
"menu": "some menu",
"button": "some button"
}
// PUT /api/sso/role/item/:id
// 路径中的 id 指需要被修改的 item id
// 修改是一个全量操作,即使数据没有发生变化,也需要传递回来,否则会被置空
// name/method/path 为必输字段
// name 字段不可重复
// 如果原来的数据的状态是 deleted,修改后,就会取消删除状态
{
"name": "读取用户明细",
"method": "GET",
"path": "/api/sso/user/*",
"resource": "",
"menu": "some menu",
"button": "some button"
}
// DELETE /api/sso/role/item/:id
// 路径中的 id 指的是需要被删除的 item id
// 删除是对数据做一个 deleted 标记
// 已删除的数据,可以使用 修改 item 接口重新上线
// GET /api/sso/role/item/:id
// 路径中的 id 指的是需要读取信息的 item id
// GET /api/sso/role/items
// 支持的 url 参数如下,这些参数可以同时传递
// name - 支持部分匹配
// path - 支持部分匹配
// method - 可选值为 http method,比如 GET POST 等
// menu - 支持部分匹配
// button - 支持部分匹配
// deleted - 是否删除,可选值为 true/false
// page - 分页,从 1 开始
// size - 单页条数,默认 10
// POST /api/sso/role/permission
// name 为必输参数
// itemIds 指的是 item 的 id,本接口中可以选择输入,也可以不输入
{
"name": "管理用户基本信息",
"itemIds": ["ida", "idb"],
"menu": "xxx",
"button": "yyy"
}
// POST /api/sso/role/permission/:id/additems
// 路径中 id 指的是被修改的 permission 的 id
// itemIds 指的是要添加的 item 的 id 列表
{
"itemIds": ["ida", "idb"]
}
// POST /api/sso/role/permission/:id/delitems
// 路径中 id 指的是被修改的 permission 的 id
// itemIds 指的是要添加的 item 的 id 列表
{
"itemIds": ["ida", "idb"]
}
// PUT /api/sso/role/permission/:id
// 修改的是除了包含的 item id 外的其他信息
{
"name": "some name",
"menu": "some menu",
"button": "some button"
}
// DELETE /api/sso/role/permission/:id
// 删除是标记操作
// 已经删除的数据可以通过 修改 permission 基本信息 接口再重新上线
// GET /api/sso/role/permission/:id
// GET /api/sso/role/permissions
// 支持的 url 参数如下
// 以下参数支持同时传递生效
// name - 支持部分匹配
// menu - 支持部分匹配
// button - 支持部分匹配
// deleted - 是否删除,可选值为 true/false
// page - 当前页,默认 1
// size - 单页条数,默认 10
// POST /api/sso/role/role
// name 为必填,不可重复,其他为选填
{
"name": "role name",
"pids": ["pid1", "pid2"],
"menu": "some menu",
"button": "some button"
}
// POST /api/sso/role/role/:id/addps
// 路径中 id 指的是 role id
// 可以同时添加多个 permission, pids 指的是 permission 的 id
{
"pids": ["pid1", "pid2"]
}
// POST /api/sso/role/role/:id/delps
// 路径中的 id 指的是 role id
// 可以同时删除多个 permission
{
"pids": ["pid1", "pid2"]
}
// PUT /api/sso/role/role/:id
// 路径中的 id 指的是 role id
{
"name": "role name",
"menu": "some munu",
"button": "some button"
}
// DELETE /api/sso/role/role/:id
// 删除是标记操作
// 已经删除的数据可以通过 修改 role信息 接口再重新上线
// POST /api/sso/role/:id/addchildrole
// 此处添加的子角色,是为了辅助用户创建账户时,方便给账户赋予角色,赋予的角色只能是此处的角色
// :id 指的是目标 role id
{
"childrenRole": [
{
"id": "abccc",
"name": "角色1"
},
{
"id": "iddd2",
"name": "角色2"
}
]
}
// POST /api/sso/user/:id/delchildrole
// 移除此 :id 角色包含的 children role
{
"childrenRole": [
{
"id": "abccc",
"name": "角色1"
},
{
"id": "iddd2",
"name": "角色2"
}
]
}
// GET /api/sso/role/role/:id
// GET /api/sso/role/roles
// 支持的 url 参数如下
// 以下参数支持同时传递生效
// name - 支持部分匹配
// menu - 支持部分匹配
// button - 支持部分匹配
// deleted - 是否删除,可选值为 true/false
// page - 当前页,默认 1
// size - 单页条数,默认 10
管理用户和角色的映射关系
// POST /api/sso/uwr/addroles
// userId 与 roleIds 为必填
{
"userId": "userid",
"userName": "some user name",
"avatar": "user avatar url",
"roleIds": ["roleid1", "roleid2"]
}
// POST /api/sso/uwr/delroles
// 两个参数都是必输
{
"userId": "userid",
"roleIds": ["roleid1", "roleid2"]
}
// GET /api/sso/uwr/user/:id
// 路径中的 id 指的是 userid
// GET /api/sso/uwr/users
// 仅支持 page size 参数
AuthOpton 结构体
type Option struct {
R *redis.Client
Mgo *dbandmq.MgoOption
db *dbandmq.Ds // 临时存放,使用完毕会销毁
}
var AuthOption = &auth.Option{} // 调用本包,需要给这个变量赋值
1、初始化数据库连接需要的参数信息,给 AuthOption 变量赋值
2、调用初始化方法 InitAuth()
2、直接调用 Auth(c *gin.Context) 即可
下面十一个例子
var err error
rOpt := &dbandmq.RedisOption{
Host: conf.Auth.Redis.Host,
Port: conf.Auth.Redis.Port,
Passwd: conf.Auth.Redis.Passwd,
DbNum: conf.Auth.Redis.Db,
}
redisC, err := dbandmq.NewRedisClient(rOpt)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
ao = &auth.Option{
R: redisC,
Ds: ds,
}
err = ao.InitAuth()
如果想要更加详细的调用,第一步也是给 AuthOption 变量赋值
然后调用 AuthLoginAndRole(ao *Option, token, method, uri, resource string)
根据返回的 AuthResult 结构自行判断。
const (
AuthResultInValidToken = 0 // token 错误,比如用户名或密码错误
AuthResultInValidRole = 1 // role 不对,无对应的操作权限
AuthResultNeedChangePasswd = 2 // 密码被初始化了,需要修改密码
AuthResultOK = 9 // 验证成功
)
type AuthResult struct {
Result int `json:"result"` // 验证结果,见上面字典
User *userapp.User `json:"user"` // 用户信息
Roles []*roleapp.Role `json:"roles"` // 角色信息
}
具体可以见上面的接口。