Browse Source

宝钢统一认证

hsun 1 week ago
parent
commit
a312620719

+ 12 - 0
config/config.go

@@ -11,6 +11,7 @@ type Config struct {
 	Xiangyu   Xiangyu   `mapstructure:"xiangyu" json:"xiangyu" yaml:"xiangyu"`
 	PCSG      PCSG      `mapstructure:"pcsg" json:"pcsg" yaml:"pcsg"`
 	HTFutures HTFutures `mapstructure:"htFutures" json:"htFutures" yaml:"htFutures"`
+	Baosteel  Baosteel  `mapstructure:"baosteel" json:"baosteel" yaml:"baosteel"`
 }
 
 // Serve gin服务配置
@@ -143,3 +144,14 @@ type SyncTask struct {
 type PCSG struct {
 	BloombergApiUrl string `mapstructure:"bloomberge-api-url" json:"bloomberge-api-url" yaml:"bloomberge-api-url" description:"彭博API服务地址"`
 }
+
+// Baosteel 宝钢的配置
+type Baosteel struct {
+	UserAuthHost         string `mapstructure:"user-auth-host" json:"user-auth-host" yaml:"user-auth-host" description:"统一认证地址"`
+	UserAuthClientId     string `mapstructure:"user-auth-client-id" json:"user-auth-client-id" yaml:"user-auth-client-id" description:"应用登记ID"`
+	UserAuthClientSecret string `mapstructure:"user-auth-client-secret" json:"user-auth-client-secret" yaml:"user-auth-client-secret" description:"应用登记密钥"`
+	UserAuthRedirectUrl  string `mapstructure:"user-auth-redirect-url" json:"user-auth-redirect-url" yaml:"user-auth-redirect-url" description:"回调地址"`
+	UserAuthCallbackUrl  string `mapstructure:"user-auth-callback-url" json:"user-auth-callback-url" yaml:"user-auth-callback-url" description:"登出地址"`
+	DefaultDepartmentId  int    `mapstructure:"default-department-id" json:"default-department-id" yaml:"default-department-id" description:"默认部门ID"`
+	DefaultRoleId        int    `mapstructure:"default-role-id" json:"default-role-id" yaml:"default-role-id" description:"默认角色ID"`
+}

+ 94 - 0
controller/baosteel/auth.go

@@ -0,0 +1,94 @@
+package baosteel
+
+import (
+	"eta/eta_bridge/controller/resp"
+	"eta/eta_bridge/global"
+	baosteelLogic "eta/eta_bridge/logic/baosteel"
+	baosteelReq "eta/eta_bridge/models/request/baosteel"
+	"github.com/gin-gonic/gin"
+	"github.com/go-playground/validator/v10"
+)
+
+// BaoSteelController 宝钢
+type BaoSteelController struct{}
+
+// GetToken
+// @Description: 获取token
+func (this *BaoSteelController) GetToken(c *gin.Context) {
+	var req baosteelReq.GetTokenReq
+	if e := c.Bind(&req); e != nil {
+		err, ok := e.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
+		return
+	}
+	if req.Code == "" {
+		resp.FailMsg("请传入code码", "请输入指标code码", c)
+		return
+	}
+
+	result, err, errMsg := baosteelLogic.LoginEta(req.Code)
+	if err != nil {
+		resp.FailData(errMsg, err.Error(), c)
+		return
+	}
+	resp.OkData("获取成功", result, c)
+	return
+}
+
+// RefreshToken
+// @Description: 刷新token
+func (this *BaoSteelController) RefreshToken(c *gin.Context) {
+	var req baosteelReq.RefreshTokenReq
+	if e := c.Bind(&req); e != nil {
+		err, ok := e.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
+		return
+	}
+	if req.RefreshToken == "" {
+		resp.FailMsg("请传入refresh_token", "请传入refresh_token", c)
+		return
+	}
+
+	err := baosteelLogic.RefreshToken(req.RefreshToken)
+	if err != nil {
+		resp.FailData("刷新失败", err.Error(), c)
+		return
+	}
+	resp.Ok("刷新成功", c)
+	return
+}
+
+// RevokeToken
+// @Description: 销毁token
+func (this *BaoSteelController) RevokeToken(c *gin.Context) {
+	var req baosteelReq.RevokeTokenReq
+	if e := c.Bind(&req); e != nil {
+		err, ok := e.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
+		return
+	}
+	if req.Token == "" {
+		resp.FailMsg("请传入token", "请传入token", c)
+		return
+	}
+
+	err := baosteelLogic.RevokeToken(req.Token)
+	if err != nil {
+		resp.FailData("销毁失败", err.Error(), c)
+		return
+	}
+	resp.Ok("销毁成功", c)
+	return
+}

+ 1 - 0
init_serve/router.go

@@ -23,5 +23,6 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitXiangyu(rBase)
 	routers.InitPCSG(rBase)
 	routers.InitHTSSO(rBase)
+	routers.InitBaosteel(rBase)
 	return
 }

+ 73 - 0
logic/baosteel/auth.go

@@ -0,0 +1,73 @@
+package baosteel
+
+import (
+	"eta/eta_bridge/global"
+	"eta/eta_bridge/models/eta"
+	"eta/eta_bridge/models/response"
+	"eta/eta_bridge/services"
+	baosteelService "eta/eta_bridge/services/baosteel"
+	"fmt"
+	"time"
+)
+
+func LoginEta(code string) (resp response.LoginResp, err error, errMsg string) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("Baosteel login eta err: %v", err)
+			fmt.Println(tips)
+			global.FILE_LOG.Error(tips)
+		}
+	}()
+
+	// 获取token
+	tokenResp, e := baosteelService.GetToken(code)
+	if e != nil {
+		err = fmt.Errorf("获取AccessToken失败, %v", e)
+		return
+	}
+
+	// 获取token对应用户信息
+	userResp, e := baosteelService.GetUserInfo(tokenResp.AccessToken)
+	if e != nil {
+		err = fmt.Errorf("AccessToken获取用户信息失败, %v", e)
+		return
+	}
+
+	// 获取/创建eta用户信息
+	adminInfo, e := baosteelService.GetOrCreateEtaUserByUserResp(userResp)
+	if e != nil {
+		err = fmt.Errorf("OutId获取用户信息失败, %v", e)
+		return
+	}
+
+	// 生成登录session
+	loginResp, session, e, errMsg := services.CreateEtaSession(adminInfo)
+	if e != nil {
+		err = fmt.Errorf("生成登录session失败, %v", e)
+		return
+	}
+	resp = loginResp
+
+	// 记录两方session的绑定信息
+	thirdSession := &eta.SysThirdSession{
+		ID:                0,
+		SysUserID:         uint64(session.SysUserId),
+		UserName:          session.UserName,
+		AccessToken:       session.AccessToken,
+		ThirdAccessToken:  tokenResp.AccessToken,
+		ThirdRefreshToken: tokenResp.RefreshToken,
+		ThirdExpiredTime:  time.Now().Add(time.Duration(tokenResp.ExpiresIn-100) * time.Second),
+		CreatedTime:       time.Now(),
+		LastUpdatedTime:   time.Now(),
+	}
+	_ = eta.AddSysThirdSession(thirdSession)
+	return
+}
+
+func RefreshToken(refreshToken string) (err error) {
+	return baosteelService.RefreshToken(refreshToken)
+}
+
+func RevokeToken(token string) (err error) {
+	return baosteelService.RevokeToken(token)
+}

+ 9 - 9
models/eta/sys_third_session.go

@@ -8,15 +8,15 @@ import (
 // SysThirdSession
 // @Description: 第三方登录会话session
 type SysThirdSession struct {
-	ID               uint64 `gorm:"primaryKey;column:id"`
-	SysUserID        uint64 `gorm:"column:sys_user_id"`
-	UserName         string `gorm:"column:user_name"`
-	AccessToken      string `gorm:"index:access_token;column:access_token"`
-	ThirdAccessToken string `gorm:"index:third_access_token;column:third_access_token"`
-	//ThirdRefreshToken string    `gorm:"column:third_refresh_token"`
-	ThirdExpiredTime time.Time `gorm:"column:third_expired_time"`
-	CreatedTime      time.Time `gorm:"index:created_time;column:created_time"`
-	LastUpdatedTime  time.Time `gorm:"index:last_updated_time;column:last_updated_time"`
+	ID                uint64    `gorm:"primaryKey;column:id"`
+	SysUserID         uint64    `gorm:"column:sys_user_id"`
+	UserName          string    `gorm:"column:user_name"`
+	AccessToken       string    `gorm:"index:access_token;column:access_token"`
+	ThirdAccessToken  string    `gorm:"index:third_access_token;column:third_access_token"`
+	ThirdRefreshToken string    `gorm:"column:third_refresh_token"`
+	ThirdExpiredTime  time.Time `gorm:"column:third_expired_time"`
+	CreatedTime       time.Time `gorm:"index:created_time;column:created_time"`
+	LastUpdatedTime   time.Time `gorm:"index:last_updated_time;column:last_updated_time"`
 }
 
 func (m *SysThirdSession) TableName() string {

+ 16 - 0
models/request/baosteel/auth.go

@@ -0,0 +1,16 @@
+package baosteel
+
+// GetTokenReq 获取token请求体
+type GetTokenReq struct {
+	Code string `json:"code" form:"code" description:"code编码"`
+}
+
+// RefreshTokenReq 刷新token请求体
+type RefreshTokenReq struct {
+	RefreshToken string `json:"refresh_token" form:"refresh_token" description:"刷新token"`
+}
+
+// RevokeTokenReq 销毁token请求体
+type RevokeTokenReq struct {
+	Token string `json:"token" form:"token" description:"token"`
+}

+ 1 - 0
models/response/auth.go

@@ -10,4 +10,5 @@ type LoginResp struct {
 	AdminId         int    `description:"系统用户id"`
 	ProductName     string `description:"产品名称:admin,ficc,权益"`
 	Authority       int    `description:"管理权限,0:无,1:部门负责人,2:小组负责人,或者ficc销售主管,4:ficc销售组长"`
+	Enabled         int    `description:"禁启用状态:0-禁用;1-启用"`
 }

+ 15 - 0
routers/baosteel.go

@@ -0,0 +1,15 @@
+package routers
+
+import (
+	"eta/eta_bridge/controller/baosteel"
+	"github.com/gin-gonic/gin"
+)
+
+// InitBaosteel 宝钢接口
+func InitBaosteel(r *gin.RouterGroup) {
+	control := new(baosteel.BaoSteelController)
+	group := r.Group("baosteel/")
+	group.POST("auth/getToken", control.GetToken)
+	group.GET("auth/refreshToken", control.RefreshToken)
+	group.POST("auth/revokeToken", control.RevokeToken)
+}

+ 166 - 0
services/baosteel/auth.go

@@ -0,0 +1,166 @@
+package baosteel
+
+import (
+	"encoding/json"
+	"eta/eta_bridge/global"
+	"fmt"
+	"io"
+	"net/http"
+	"strings"
+)
+
+func HttpGetAuth(urlPath string) ([]byte, error) {
+	if global.CONFIG.Baosteel.UserAuthHost == `` {
+		return nil, fmt.Errorf("统一认证地址为空")
+	}
+	getUrl := global.CONFIG.Baosteel.UserAuthHost + urlPath
+
+	client := &http.Client{}
+	req, err := http.NewRequest("GET", getUrl, nil)
+	if err != nil {
+		return nil, err
+	}
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	result, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	tips := fmt.Sprintf("Baosteel统一认证: %s;\n返回参数:%s\n", getUrl, string(result))
+	global.FILE_LOG.Debug(tips)
+
+	//  解析返回参数,判断是否是json
+	if !json.Valid(result) {
+		err = fmt.Errorf("返回参数不是json格式")
+	}
+	return result, err
+}
+
+func HttpPostAuth(urlPath, postData, accessToken string, params ...string) ([]byte, error) {
+	if global.CONFIG.Baosteel.UserAuthHost == `` {
+		return nil, fmt.Errorf("统一认证地址为空")
+	}
+	postUrl := global.CONFIG.Baosteel.UserAuthHost + urlPath
+
+	body := io.NopCloser(strings.NewReader(postData))
+	client := &http.Client{}
+	req, err := http.NewRequest("POST", postUrl, body)
+	if err != nil {
+		return nil, err
+	}
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	req.Header.Set("content-Type", contentType)
+	if accessToken != "" {
+		token := fmt.Sprintf(`Bearer %s`, accessToken)
+		req.Header.Set("Authorization", token)
+	}
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	result, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	tips := fmt.Sprintf("Baosteel统一认证: %s;\n请求参数:%s;\n返回参数:%s\n", postUrl, postData, string(result))
+	global.FILE_LOG.Debug(tips)
+
+	//  解析返回参数,判断是否是json
+	if !json.Valid(result) {
+		err = fmt.Errorf("返回参数不是json格式")
+	}
+	return result, err
+}
+
+type GetTokenResp struct {
+	AccessToken  string `json:"access_token"`
+	RefreshToken string `json:"refresh_token"`
+	ExpiresIn    int    `json:"expires_in"`
+}
+
+func GetToken(code string) (resp *GetTokenResp, err error) {
+	// http://eplat.baogang.info/base-security-service/oauth/token?client_id=piosbguy844Y83wv2Ma26Y &client_secret=3AE9D870EEBF59F34F697E6DE531933D&code=dy9KF1&grant_type=authorization _code&redirect_uri=http://10.70.16.180:8080/apps/pios/index
+	urlPath := fmt.Sprintf(`/oauth/token?client_id=%s&client_secret=%s&code=%s&grant_type=authorization_code&redirect_uri=%s`, global.CONFIG.Baosteel.UserAuthClientId, global.CONFIG.Baosteel.UserAuthClientSecret, code, global.CONFIG.Baosteel.UserAuthRedirectUrl)
+
+	result, e := HttpPostAuth(urlPath, ``, "", "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("result unmarshal err: %v", e)
+		return
+	}
+	//global.FILE_LOG.Debug(fmt.Sprintf("Baosteel GetToken Resp: %s", string(result)))
+	return
+}
+
+type UserInfoResp struct {
+	Birthday       string `json:"birthday"`
+	Gender         int    `json:"gender"`
+	IdCardNo       string `json:"idCardNo"`
+	Mobile         string `json:"mobile"`
+	HeadUrl        string `json:"headUrl"`
+	UserName       string `json:"userName"`
+	UserId         string `json:"userId"`
+	RealName       string `json:"realName"`
+	LoginName      string `json:"loginName"`
+	IsLocked       string `json:"isLocked"`
+	ContactAddress string `json:"contactAddress"`
+	Email          string `json:"email"`
+	Age            int    `json:"age"`
+	Status         string `json:"status"`
+}
+
+func GetUserInfo(token string) (resp *UserInfoResp, err error) {
+	// http://eplat.baogang.info/base-security-service/user
+	urlPath := `/user`
+
+	// access_token在header中
+	result, e := HttpPostAuth(urlPath, "", token, "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf("result unmarshal err: %v", e)
+		return
+	}
+	//global.FILE_LOG.Debug(fmt.Sprintf("Baosteel GetUserInfo Resp: %s", string(result)))
+	return
+}
+
+func RefreshToken(refreshToken string) (err error) {
+	// http://eplat.baogang.info/base-security-service/oauth/token?client_id=piosbguy844Y83wv2Ma26Y&client_secret=3AE9D870EEBF59F34F697E6DE531933D&grant_type=refresh_token&refresh_toke n=eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp
+	urlPath := fmt.Sprintf(`/oauth/token?client_id=%s&client_secret=%s&code=%s&grant_type=refresh_token&refresh_toke=%s`, global.CONFIG.Baosteel.UserAuthClientId, global.CONFIG.Baosteel.UserAuthClientSecret, refreshToken, global.CONFIG.Baosteel.UserAuthRedirectUrl)
+
+	_, e := HttpPostAuth(urlPath, ``, "", "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	//global.FILE_LOG.Debug(fmt.Sprintf("Baosteel RefreshToken Resp: %s", string(result)))
+	return
+}
+
+func RevokeToken(token string) (err error) {
+	// http://eplat.baogang.info/base-security-service/logout?callback=http://10.70.16.180:8080/apps/pios&token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6InBpb3NiZ3V5ODQ0WTgzd3YyT WEyNlkiLCJ1c2VyX25hbWUiOiI3MDI0ODEiLCJsb2dpbk5hbWUiOiI3MDI0ODEiLCJleHAiOjE3NDEzMT U4NzIsInVzZXJOYW1lIjoi5b6Q6ICAIiwidHlwZSI6InVzZXIiLCJ1c2VySWQiOiI3MDI
+	urlPath := fmt.Sprintf(`/logout?callback=%s&token=%s`, global.CONFIG.Baosteel.UserAuthCallbackUrl, token)
+
+	_, e := HttpPostAuth(urlPath, ``, "", "application/json")
+	if e != nil {
+		err = fmt.Errorf("http post err: %v", e)
+		return
+	}
+	//global.FILE_LOG.Debug(fmt.Sprintf("Baosteel RevokeToken Resp: %s", string(result)))
+	return
+}

+ 85 - 0
services/baosteel/user.go

@@ -0,0 +1,85 @@
+package baosteel
+
+import (
+	"eta/eta_bridge/global"
+	"eta/eta_bridge/models/eta"
+	"eta/eta_bridge/utils"
+	"fmt"
+	"time"
+)
+
+func GetOrCreateEtaUserByUserResp(userResp *UserInfoResp) (etaAdmin *eta.Admin, err error) {
+	if userResp == nil {
+		err = fmt.Errorf("Baosteel用户信息有误")
+		return
+	}
+	if userResp.UserId == "" {
+		err = fmt.Errorf("Baosteel用户ID有误")
+		return
+	}
+	sysUser, e := eta.GetSysUserByAdminName(userResp.UserId)
+	if e != nil && e != utils.ErrNoRow {
+		err = fmt.Errorf("UserId获取系统用户失败, %v", e)
+		return
+	}
+
+	// 更新用户最后登录时间,工号和外部ID
+	if sysUser != nil && sysUser.AdminId > 0 {
+		var updateCols []string
+		if sysUser.EmployeeId == "" {
+			sysUser.EmployeeId = userResp.UserId
+			updateCols = append(updateCols, "employee_id")
+		}
+		if sysUser.OutID == "" {
+			sysUser.OutID = userResp.UserId
+			updateCols = append(updateCols, "out_id")
+		}
+		sysUser.LastLoginTime = time.Now().Local()
+		updateCols = append(updateCols, "last_login_time")
+		if e = sysUser.Update(updateCols); e != nil {
+			err = fmt.Errorf("更新系统用户失败, %v", e)
+			return
+		}
+		etaAdmin = sysUser
+		return
+	}
+
+	// 新增用户,默认禁用,角色none,部门None
+	roleInfo, e := eta.GetSysRoleById(global.CONFIG.Baosteel.DefaultRoleId)
+	if e != nil {
+		err = fmt.Errorf("获取默认角色失败, %v", e)
+		return
+	}
+	departmentInfo, e := eta.GetDepartmentById(global.CONFIG.Baosteel.DefaultDepartmentId)
+	if e != nil {
+		err = fmt.Errorf("获取默认部门失败, %v", e)
+		return
+	}
+	newAdmin := &eta.Admin{
+		AdminName:       userResp.UserId,
+		RealName:        userResp.UserName,
+		Password:        utils.MD5(fmt.Sprintf("Password%s", userResp.UserId)),
+		Enabled:         1,
+		Email:           fmt.Sprintf("%s@baosteel.com", userResp.UserId),
+		LastLoginTime:   time.Now().Local(),
+		CreatedTime:     time.Now().Local(),
+		LastUpdatedTime: time.Now().Local(),
+		Mobile:          userResp.Mobile,
+		RoleId:          roleInfo.RoleId,
+		RoleName:        roleInfo.RoleName,
+		RoleTypeCode:    roleInfo.RoleTypeCode,
+		DepartmentId:    departmentInfo.DepartmentId,
+		DepartmentName:  departmentInfo.DepartmentName,
+		EmployeeId:      userResp.UserId,
+		TelAreaCode:     "86",
+		Province:        "上海市",
+		City:            "上海市",
+		OutID:           userResp.UserId,
+	}
+	if e = newAdmin.Create(); e != nil {
+		err = fmt.Errorf("新增系统用户失败, %v", e)
+		return
+	}
+	etaAdmin = newAdmin
+	return
+}

+ 1 - 0
services/session.go

@@ -68,6 +68,7 @@ func CreateEtaSession(sysUser *eta.Admin) (login response.LoginResp, session *et
 	login.SysRoleTypeCode = sysUser.RoleTypeCode //系统角色编码
 	login.RoleTypeCode = sysUser.RoleTypeCode
 	login.Authority = sysUser.Authority
+	login.Enabled = sysUser.Enabled
 
 	// 判断实际的角色类型
 	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_GROUP {