作者 yangfu

Merge branch 'dev' of http://gitlab.fjmaimaimai.com/mmm-go/oppmg into dev

# Conflicts:
#	models/user_company.go
#	services/auth/auth.go
... ... @@ -2,10 +2,10 @@
| 功能 | 完成状态 | 时间 | 接口路径 | 请求方式 |
| -------------- | ------------------ | --------------- | --------------------------------- | -------- |
| 登录获取 token | 进行中 | | /auth/login | post |
| 登录获取 token | 完成 | 2018/12/11 | /auth/login | post |
| 短信验证码 | 未开始 | | |
| 刷新 token | 未开始 | | /v1/auth/refresh_token | post |
| 切换公司 | 未开始 | | /v1/auth/change_company |
| 刷新 token | 完成 | 2018/12/11 | /v1/auth/refresh_token | get |
| 切换公司 | 完成 | 2018/12/11 | /v1/auth/change_company | post |
| 获取角色列表 | 完成 | | /v1/rbac/:companyid/role | get |
| 添加角色 | 完成 | 2019.11.26 | /v1/rbac/role | post |
| 编辑角色 | 完成 | 2019.11.26 | /v1/rbac/role | put |
... ...
... ... @@ -27,9 +27,9 @@ log_level = "${LOG_LEVEL||error}"
##统一用户中心相关配置
ucenter_check_alt = "rsF0pL!6DwjBO735"
ucenter_base_url = "suplus-ucenter-dev.fjmaimaimai.com"
ucenter_secret = "12412213"
ucenter_app_key = "111222"
ucenter_base_url = "http://suplus-ucenter-dev.fjmaimaimai.com"
ucenter_app_key = "39aefef9e22744a3b2d2d3791824ae7b"
ucenter_secret = "39aefef9e22744a3b2d2d3791824ae7b"
# 审批流程修改 消息发布
message_publish = "audit_change"
#---自定义配置 结束----
\ No newline at end of file
... ...
... ... @@ -20,14 +20,19 @@ func (c *AuthController) URLMapping() {
// RefreshToken ....
// @router /refresh_token [get]
func (c *AuthController) RefreshToken() {
log.Debug("运行cotrollers")
var msg *protocol.ResponseMessage
defer func() {
c.ResposeJson(msg)
}()
// data, commErr := auth.GetAccessToken(param)
// msg = protocol.NewReturnResponse(data, commErr)
companyid := c.GetCompanyId()
userid := c.GetUserId()
logintoken, err := serveauth.ChangeLoginToken(userid, companyid)
if err != nil {
msg = protocol.NewReturnResponse(nil, err)
return
}
err = serveauth.ResetLoginTokenRedis(logintoken)
msg = protocol.NewReturnResponse(logintoken, err)
return
}
... ... @@ -49,12 +54,18 @@ func (c *AuthController) Login() {
msg = protocol.BadRequestParam("10021")
return
}
logintoken, err := serveauth.LoginAuthByPassword(param.Account, param.Password)
// logintoken, err := serveauth.LoginAuthByPassword(param.Account, param.Password)
// if err != nil {
// msg = protocol.NewReturnResponse(nil, err)
// return
// }
// err = serveauth.ResetLoginToken(logintoken)
logintoken, err := serveauth.LoginAuthByUCenter(param.Account, param.Password)
if err != nil {
msg = protocol.NewReturnResponse(nil, err)
return
}
err = serveauth.ResetLoginToken(logintoken)
err = serveauth.ResetLoginTokenRedis(logintoken)
msg = protocol.NewReturnResponse(logintoken, err)
return
}
... ... @@ -78,13 +89,12 @@ func (c *AuthController) ChangeCompany() {
msg = protocol.BadRequestParam("1")
return
}
logintoken, err := serveauth.ChangeLoginToken(userid, param.CompanyId)
if err != nil {
msg = protocol.NewReturnResponse(nil, err)
return
}
err = redisdata.SetLoginToken(logintoken, userid)
err = redisdata.SetLoginToken(logintoken, userid, param.CompanyId)
if err != nil {
log.Error("redisdata.SetLoginToken err:%s", err)
}
... ...
... ... @@ -86,6 +86,7 @@ func (c *RbacController) RoleDelete() {
}
err := serverbac.RoleDelete(param)
msg = protocol.NewReturnResponse(nil, err)
return
}
... ... @@ -158,6 +159,7 @@ func (c *RbacController) RoleGroupDelete() {
msg = protocol.BadRequestParam("1")
return
}
err := serverbac.RoleGroupDelete(param)
msg = protocol.NewReturnResponse(nil, err)
return
... ...
... ... @@ -6,7 +6,6 @@ import (
"oppmg/common/config"
"oppmg/common/log"
"oppmg/middleware"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
... ... @@ -22,7 +21,6 @@ func main() {
// beego.BConfig.WebConfig.DirectoryIndex = true
// beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
// }
beego.InsertFilter("*", beego.BeforeExec, middleware.LogRouter)
log.Debug("应用启动")
beego.Run()
}
... ...
... ... @@ -15,10 +15,14 @@ import (
//LogRequestData Before Router
var LogRequestData = func(ctx *context.Context) {
log.Info("====>Recv Request:%s", ctx.Input.URI())
hmap := map[string]string{
protocol.HeaderAccessToken: ctx.Input.Header(protocol.HeaderAccessToken),
protocol.HeaderRefreshToken: ctx.Input.Header(protocol.HeaderRefreshToken),
}
if ctx.Input.RequestBody != nil {
log.Info("====>Recv data from client:\nHeadData: %s \nBodyData: %s", ctx.Request.Header, string(ctx.Input.RequestBody))
log.Info("====>Recv data from client:\nHeadData: %v \nBodyData: %s", hmap, string(ctx.Input.RequestBody))
} else {
log.Info("====>Recv data from client:\nHeadData: %s ", ctx.Request.Header)
log.Info("====>Recv data from client:\nHeadData: %v ", hmap)
}
}
... ... @@ -50,7 +54,7 @@ var LogRequestData = func(ctx *context.Context) {
var AuthToken = func(ctx *context.Context) {
log.Debug("执行中间件AuthToken")
var (
storetoken protocol.LoginAuthToken
storetoken redisdata.RedisLoginToken
msg *protocol.ResponseMessage
err error
mtoken *serveauth.MyToken
... ... @@ -61,7 +65,7 @@ var AuthToken = func(ctx *context.Context) {
if err == nil {
storetoken, err = redisdata.GetLoginToken(mtoken.UID)
if err != nil {
log.Error("err:%s", err)
log.Error("redisdata.GetLoginToken err:%s", err)
msg = protocol.NewMesage("10024")
ctx.Output.JSON(msg, false, false)
return
... ... @@ -110,3 +114,5 @@ var LogRouter = func(ctx *context.Context) {
fmt.Println("====>r:", p)
return
}
//登录失效
... ...
... ... @@ -10,7 +10,7 @@ import (
type Company struct {
Id int64 `orm:"column(id);auto"`
Name string `orm:"column(name);size(40)"`
UserId int64 `orm:"column(user_id)"`
Admin_id int64 `orm:"column(admin_id)"`
CreateAt time.Time `orm:"column(create_at);type(timestamp);auto_now"`
UpdateAt time.Time `orm:"column(update_at);type(timestamp)"`
DeleteAt time.Time `orm:"column(delete_at);type(timestamp)"`
... ...
package models
import (
"errors"
"fmt"
"time"
... ... @@ -92,6 +93,9 @@ func GetUserByPhone(phone string) (v *User, err error) {
if err = o.Read(v, "Phone"); err == nil {
return v, nil
}
if v.DeleteAt.Unix() > 0 {
return nil, errors.New("user is deleted")
}
return nil, err
}
... ...
... ... @@ -67,7 +67,7 @@ func UpdateUserAuthById(m *UserAuth, col []string) (err error) {
// ascertain id exists in the database
var num int64
if num, err = o.Update(m, col...); err == nil {
log.Info("Number of records updated in database:", num)
log.Info("Number of records updated in database:%d", num)
}
return
}
... ...
... ... @@ -2,6 +2,7 @@ package models
import (
"fmt"
"oppmg/common/log"
"time"
"github.com/astaxie/beego/orm"
... ... @@ -40,6 +41,7 @@ func (t *UserCompany) IsEnable() bool {
}
func (t *UserCompany) IsDelete() bool {
log.Debug("deleteTime:%d", t.DeleteAt.Unix())
if t.DeleteAt.Unix() > 0 {
return true
}
... ... @@ -85,8 +87,11 @@ func GetUserCompanyBy(userid int64, companyId int64) (*UserCompany, error) {
}
return v, nil
}
<<<<<<< HEAD
func GetUserCompanyByUser(userid int64) ([]UserCompany, error) {
//datasql := ``
return nil, nil
}
=======
>>>>>>> 626a6b6d8e73bd83579be13a797ab6c1fce8d3d8
... ...
... ... @@ -12,6 +12,7 @@ func init() {
nsV1 := beego.NewNamespace("v1",
beego.NSBefore(middleware.AllowOption),
beego.NSBefore(middleware.LogRequestData),
beego.NSBefore(middleware.AuthToken),
beego.NSNamespace("/company",
beego.NSRouter("/:companyid([0-9]+)/department", &controllers.CompanyController{}, "get:DepartmentList"),
beego.NSRouter("/department/:id([0-9]+)", &controllers.CompanyController{}, "get:DepartmentOne"),
... ... @@ -34,7 +35,7 @@ func init() {
),
beego.NSNamespace("/auth",
beego.NSRouter("/change_company", &controllers.AuthController{}, "post:ChangeCompany"),
beego.NSRouter("/refresh_token", &controllers.AuthController{}, "post:RefreshToken"),
beego.NSRouter("/refresh_token", &controllers.AuthController{}, "get:RefreshToken"),
),
beego.NSNamespace("/bulletin",
beego.NSRouter("/release", &controllers.BulletinController{}, "post:BulletinRelease"),
... ...
... ... @@ -12,6 +12,7 @@ import (
"oppmg/protocol"
"oppmg/services/ucenter"
"oppmg/storage/redisdata"
"oppmg/utils"
"strings"
"time"
... ... @@ -41,6 +42,7 @@ func validatePassword(from, to string) bool {
}
//LoginAuth 登录认证
//TODO 登录校验逻辑修改
func LoginAuthByPassword(account, password string) (protocol.LoginAuthToken, error) {
var (
user *models.User
... ... @@ -139,7 +141,7 @@ func ResetLoginToken(loginToken protocol.LoginAuthToken) error {
return nil
}
// token 存redis
//ResetLoginTokenRedis token存redis
func ResetLoginTokenRedis(loginToken protocol.LoginAuthToken) error {
var (
mtoken *MyToken
... ... @@ -150,7 +152,7 @@ func ResetLoginTokenRedis(loginToken protocol.LoginAuthToken) error {
log.Error("jwt err:%s", err)
return protocol.NewErrWithMessage("1")
}
err = redisdata.SetLoginToken(loginToken, mtoken.UID)
err = redisdata.SetLoginToken(loginToken, mtoken.UID, mtoken.CompanyID)
if err != nil {
log.Error(" redisdata.SetLoginToken err:%s", err)
}
... ... @@ -168,14 +170,14 @@ func ChangeLoginToken(userid, companyid int64) (protocol.LoginAuthToken, error)
usercompany, err = models.GetUserCompanyBy(userid, companyid)
if err != nil {
log.Error("GetUserCompanyBy(userid, companyid) err:%s", err)
log.Error("GetUserCompanyBy(userid, companyid)[%d,%d] err:%s", userid, companyid, err)
return logintoken, protocol.NewErrWithMessage("1")
}
if ok := usercompany.IsEnable(); !ok {
log.Debug("公司禁用此用户")
return logintoken, protocol.NewErrWithMessage("10027")
}
if ok := usercompany.IsDelete(); !ok {
if ok := usercompany.IsDelete(); ok {
log.Debug("公司删除此用户")
return logintoken, protocol.NewErrWithMessage("10027")
}
... ... @@ -201,7 +203,7 @@ func RefreshLoginToken(refreshtoken string) (protocol.LoginAuthToken, error) {
logintoken protocol.LoginAuthToken
mtoken *MyToken
err error
storetoken protocol.LoginAuthToken
storetoken redisdata.RedisLoginToken
)
mtoken, err = ValidJWTToken(refreshtoken)
if err != nil {
... ... @@ -217,7 +219,6 @@ func RefreshLoginToken(refreshtoken string) (protocol.LoginAuthToken, error) {
return logintoken, protocol.NewErrWithMessage("10024")
}
logintoken, _ = GenerateAuthToken(mtoken.UID, mtoken.CompanyID)
ResetLoginTokenRedis(logintoken)
return logintoken, nil
}
... ... @@ -226,14 +227,33 @@ func LoginAuthByUCenter(account, password string) (protocol.LoginAuthToken, erro
err error
logintoken protocol.LoginAuthToken
uclientReturn ucenter.ResponseLogin
companyids []int64
companyid int64
userdata *models.User
)
<<<<<<< HEAD
_, err = models.GetUserByPhone(account)
=======
userdata, err = models.GetUserByPhone(account)
>>>>>>> 626a6b6d8e73bd83579be13a797ab6c1fce8d3d8
if err != nil {
log.Debug("GetUserByPhone(%s) err:%s", account, err)
return logintoken, protocol.NewErrWithMessage("10021")
}
if ok := userdata.IsEnable(); !ok {
log.Debug("userdata.IsEnable()==false")
return logintoken, protocol.NewErrWithMessage("10021")
}
if companyids, err = getUserCompanyReal(userdata.Id); err != nil {
log.Error("getUserCompanyReal err:%s", err)
return logintoken, protocol.NewErrWithMessage("10021")
}
if len(companyids) == 0 {
log.Debug("no company")
return logintoken, protocol.NewErrWithMessage("10021")
}
companyid = companyids[0]
param := ucenter.RequesLogin{
Phone: account,
Password: password,
... ... @@ -253,6 +273,34 @@ func LoginAuthByUCenter(account, password string) (protocol.LoginAuthToken, erro
uclientReturn.Msg == ucenter.ResponseMsgOk) {
return logintoken, protocol.NewErrWithMessage("10021")
}
logintoken, _ = GenerateAuthToken(userdata.Id, companyid)
return logintoken, err
}
//getUserCompanyReal 获取用户有效的公司id
func getUserCompanyReal(userid int64) (companyids []int64, err error) {
const (
datasql0 string = `SELECT b.company_id FROM user_company AS b
WHERE b.delete_at=0 AND b.enable = 1 AND b.user_id=?`
datasql2 string = `SELECT b.id FROM company AS b
WHERE b.delete_at=0 AND b.enable = 1 AND b.id in (%s) `
)
var (
ids []string
)
err = utils.ExecuteQueryAll(&ids, datasql0, userid)
if err != nil {
log.Error("EXECUTE SQL err:%s", err)
return nil, err
}
if len(ids) == 0 {
return nil, nil
}
datasql3 := fmt.Sprintf(datasql2, strings.Join(ids, ","))
err = utils.ExecuteQueryAll(&companyids, datasql3)
if err != nil {
log.Error("EXECUTE SQL err:%s", err)
return nil, err
}
return companyids, nil
}
... ...
... ... @@ -74,11 +74,11 @@ func GenerateAuthToken(uid int64, companyid int64) (protocol.LoginAuthToken, err
err error
nowtime = time.Now()
)
accesstoken, err = CreateJWTToken(uid, companyid, expiresIn+2)
accesstoken, err = CreateJWTToken(uid, companyid, nowtime.Unix()+expiresIn+2)
if err != nil {
return authToken, err
}
refreshtoken, err = CreateJWTToken(uid, companyid, refreshExpires+2)
refreshtoken, err = CreateJWTToken(uid, companyid, nowtime.Unix()+refreshExpires+2)
if err != nil {
return authToken, err
}
... ...
... ... @@ -33,7 +33,7 @@ func DepartmentAdd(param protocol.RequestDepartmentAdd) error {
for _, v := range param.Managers {
_, err = models.GetUserCompanyBy(v, param.CompanyID)
if err != nil {
e := fmt.Errorf("GetUserCompanyBy(%d, %d)", v, param.CompanyID)
e := fmt.Errorf("GetUserCompanyBy(userid,companyid)[%d, %d] err:%s", v, param.CompanyID, err)
log.Error(e.Error())
return protocol.NewErrWithMessage("1", e)
}
... ... @@ -101,7 +101,7 @@ func DepartmentEdit(param protocol.RequestDepartmentEdit) error {
for i := range diffmanage {
_, err = models.GetUserCompanyBy(diffmanage[i], param.CompanyID)
if err != nil {
e := fmt.Errorf("GetUserCompanyBy(%d,%d) err:%s", diffmanage[i], param.CompanyID, err)
e := fmt.Errorf("GetUserCompanyBy(userid,companyid)[%d,%d] err:%s", diffmanage[i], param.CompanyID, err)
log.Error(e.Error())
return protocol.NewErrWithMessage("1", e)
}
... ...
... ... @@ -64,6 +64,7 @@ func (client UCenterClient) httpDo(path string, mathod string, posts []byte) ([]
}
req.Header = client.buildHeader()
resp, err := httpclient.Do(req)
log.Info("====>Send To UCenter:%s", string(posts))
if err != nil {
return nil, err
}
... ... @@ -72,7 +73,7 @@ func (client UCenterClient) httpDo(path string, mathod string, posts []byte) ([]
if err != nil {
return nil, err
}
log.Info("====>Send To UCenter:%s", string(posts))
log.Info("<====UCenter Return:%s", string(body))
return body, nil
}
... ...
package redisdata
const (
KEY_PREFIX string = "oppmg_"
KEY_USER_TOKEN string = "token"
KEY_PREFIX string = "oppmg_" //统一前缀
KEY_USER_TOKEN string = "token" //登录token存储
)
type RedisLoginToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
CurrentCompany int64 `json:"current_company"`
IsOk bool `json:"-"`
}
... ...
... ... @@ -2,15 +2,15 @@ package redisdata
import (
"encoding/json"
"errors"
"fmt"
"oppmg/common/log"
"oppmg/common/redis"
"oppmg/protocol"
"strings"
"time"
)
func SetLoginToken(param protocol.LoginAuthToken, userid int64) error {
func SetLoginToken(param protocol.LoginAuthToken, userid int64, companyid int64) error {
client := redis.GetRedis()
var (
key string
... ... @@ -19,26 +19,33 @@ func SetLoginToken(param protocol.LoginAuthToken, userid int64) error {
exp int64
nowTime = time.Now().Unix()
)
data := RedisLoginToken{
AccessToken: param.AccessToken,
RefreshToken: param.RefreshToken,
CurrentCompany: companyid,
IsOk: true,
}
value, _ = json.Marshal(data)
exp = param.RefreshExpires - nowTime
key = fmt.Sprintf("%s%s:%d", KEY_PREFIX, KEY_USER_TOKEN, userid)
value, _ = json.Marshal(param)
err = client.Set(key, string(value), time.Duration(exp)*time.Second).Err()
return err
}
func GetLoginToken(userid int64) (protocol.LoginAuthToken, error) {
func GetLoginToken(userid int64) (RedisLoginToken, error) {
client := redis.GetRedis()
var (
key string
value string
err error
result protocol.LoginAuthToken
result RedisLoginToken
)
key = fmt.Sprintf("%s%s:%d", KEY_PREFIX, KEY_USER_TOKEN, userid)
value = client.Get(key).String()
if len(value) == 0 {
return result, errors.New("Token not found")
value, err = client.Get(key).Result()
if err != nil {
return result, err
}
value = strings.TrimSpace(value)
err = json.Unmarshal([]byte(value), &result)
if err != nil {
log.Error("Unmarshal redis value:%s err:%s", value, err)
... ...
... ... @@ -22,7 +22,7 @@ func PrintLogSql(sql string, param ...interface{}) {
//ExecuteQueryOne 执行原生sql查询单条记录;结果用结构体接收
func ExecuteQueryOne(result interface{}, sqlstr string, param ...interface{}) error {
PrintLogSql(sqlstr, param...)
var err error
o := orm.NewOrm()
err = ExecuteQueryOneWithOrmer(o, result, sqlstr, param)
... ... @@ -42,7 +42,7 @@ func ExecuteQueryOneWithOrmer(o orm.Ormer, result interface{}, sqlstr string, pa
//ExecuteQuerySql 执行原生sql查询多条记录
func ExecuteQueryAll(result interface{}, sqlstr string, param ...interface{}) error {
PrintLogSql(sqlstr, param...)
var err error
o := orm.NewOrm()
err = ExecuteQueryAllWithOrmer(o, result, sqlstr, param)
... ...
# 机会导向管理后台接口
## 全局统一设定
### 请求头指定要求的字段
| 字段 | 说明 |
| ------------------ | ---------------------------- |
| x-mmm-accesstoken | 发起请求时使用时校验用 token |
| x-mmm-refreshtoken | 刷新 token 时使用的 token |
- 备注 :token 使用 jwt 进行处理.其中包含有 user_id、company_id 的数据,登录时获取
---
### 通用响应结构
```json
{
"code": "错误码字符串",
"msg": "错误描述字符串",
"data": {
"xxx": "any"
}
}
```
- 备注:data 中的内容根据各接口实际情况确定
---
## 认证相关
### 登录
- 请求路径 :/auth/login
- 请求方式 :POST
- 请求 json:
```json
{
"account": "账号",
"password": "密码"
}
```
- 响应 json
```json
{
"code": "00000",
"msg": "成功",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTM2OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.R056B306_vO4UKfMRalncFULE5Z0phN4WOhS9PMwydc",
"expires_in": 1576053688,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTU0OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.OY54QdDwAq2B1NPnAmHkSxy_KvhktmZA2boSlcSSfoU",
"refresh_expires": 1576055488
}
}
```
- 备注:该请求无需指定请求头
---
### 刷新 token
- 请求路径 :/v1/auth/refresh_token
- 请求方式 :get
- 请求 json:
```json
```
- 响应 json
```json
{
"code": "00000",
"msg": "成功",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTM2OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.R056B306_vO4UKfMRalncFULE5Z0phN4WOhS9PMwydc",
"expires_in": 1576053688,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTU0OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.OY54QdDwAq2B1NPnAmHkSxy_KvhktmZA2boSlcSSfoU",
"refresh_expires": 1576055488
}
}
```
- 备注:无
---
### 切换公司
- 请求路径 :/v1/auth/change_company
- 请求方式 :post
- 请求 json:
```json
{
"company_id": 2
}
```
- 响应 json
```json
{
"code": "00000",
"msg": "成功",
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTM2OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.R056B306_vO4UKfMRalncFULE5Z0phN4WOhS9PMwydc",
"expires_in": 1576053688,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYwNTU0OTAsImlhdCI6MTU3NjA1MTg4OCwiaXNzIjoibW1tX29wcG1nIiwibmJmIjoxNTc2MDUxODg4LCJ1aWQiOjEwLCJjb21wYW55X2lkIjoyfQ.OY54QdDwAq2B1NPnAmHkSxy_KvhktmZA2boSlcSSfoU",
"refresh_expires": 1576055488
}
}
```
- 备注:切换公司实际是变更 token 信息
---
... ...