liuhaijun e94826ce29 add server
Change-Id: I0760f17f6a01c0121b59fcbfafc666032dbc30af
2024-09-19 09:44:15 +00:00

231 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"crypto/tls"
"encoding/json"
"fmt"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/config"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/user"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/auth"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/authen"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/errors"
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/response"
"github.com/gin-gonic/gin"
"github.com/golang/glog"
"gorm.io/gorm"
"io"
"net/http"
"regexp"
)
const (
LoginUserKey = "login-user"
)
func AuthenticationHandler() gin.HandlerFunc {
return func(c *gin.Context) {
match, _ := regexp.MatchString("/healthz", c.Request.RequestURI)
if match {
c.Next()
return
}
match, _ = regexp.MatchString("/run", c.Request.RequestURI)
if match {
c.Next()
return
}
match, _ = regexp.MatchString("/login", c.Request.RequestURI)
if match {
c.Next()
return
}
match, _ = regexp.MatchString("/api/v1/socket/*", c.Request.RequestURI)
if match {
c.Next()
return
}
match, _ = regexp.MatchString("/api/v1/*", c.Request.RequestURI)
if match {
rawToken := c.Request.Header.Get("Authorization")
if rawToken == "" {
glog.Warning("unauthorized access, token not specified")
response.Resp().FailCode(c, errors.AuthorizationError, "token should be specified in header with 'Authorization' key")
return
}
//todo 临时用
if config.Config.AppConfig.Debug {
if rawToken == "mock token" {
u, _ := user.GetUserByUsername("admin")
c.Set(LoginUserKey, u)
c.Next()
return
}
}
var username, apiToken string
ok, bearerToken := authen.JWTAuthorizer.IsBearerToken(rawToken)
if ok {
loginInfo, err := auth.Validate(bearerToken)
//marshal, _ := json.Marshal(loginInfo)
//fmt.Print(string(marshal))
if err != nil {
if authen.JWTAuthorizer.IsTokenExpired(err) {
glog.Warning("unauthorized access, bearer token expired")
response.Resp().FailCode(c, errors.AuthorizationError, "bearer token expired")
return
}
glog.Warningf("validate bearer token failed, %s", err)
response.Resp().FailCode(c, errors.AuthorizationError, fmt.Sprint("validate bearer token failed, %s", err))
return
}
username = loginInfo.Username
apiToken = loginInfo.Token
} else {
glog.Warningf("validate bearer token failed")
response.Resp().FailCode(c, errors.AuthorizationError, "validate bearer token failed")
return
}
u, err := user.GetUserByUsername(username)
if err != nil {
// 适配算网用户,支持单点登录
if config.Config.CfnConfig.Enable {
u, err = CheckUserLogin(c)
if err != nil {
glog.Errorf("unauthorized access, user not found or not login, %s", username)
response.Resp().FailCode(c, errors.AuthorizationError, "user not found or not login")
return
}
// todo
u.APIToken = apiToken
} else {
if err == gorm.ErrRecordNotFound {
glog.Errorf("unauthorized access, user not found, %s", username)
response.Resp().FailCode(c, errors.AuthorizationError, "user not found")
return
}
glog.Errorf("get user from db failed, user %s, %s", username, err)
response.Resp().FailCode(c, errors.ServerError, fmt.Sprintf("get user from db failed, user %s, %s", username, err))
return
}
}
if apiToken != "" && apiToken != u.APIToken {
glog.Warningf("unauthorized access, password mismatch, user %s", username)
response.Resp().FailCode(c, errors.AuthorizationError, "password mismatch")
return
}
c.Set(LoginUserKey, u)
c.Next()
}
//match, _ = regexp.MatchString("/", c.Request.RequestURI)
//if match {
// c.Next()
// return
//}
}
}
const AUTH_HEADER = "Authorization"
func CheckUserLogin(c *gin.Context) (*user.UserObj, error) {
url := config.Config.Auth.Url
if url == "" {
return nil, errors.NewBusinessError(errors.ServerError, "login config is not set!")
}
token := c.Request.Header.Get(AUTH_HEADER)
var client *http.Client
var request *http.Request
var resp *http.Response
client = &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}}
request, err := http.NewRequest("GET", url+config.Config.Auth.LoginInfo, nil)
if err != nil {
glog.Errorln("failed to create request [Get LoginInfo]!", err)
return nil, errors.NewBusinessError(errors.ServerError, "failed to create request [Get LoginInfo]!")
}
request.Header.Add(AUTH_HEADER, token)
resp, err = client.Do(request)
if err != nil {
glog.Errorln("failed to request [Get LoginInfo]!", err)
return nil, errors.NewBusinessError(errors.ServerError, "failed to request [Get LoginInfo]!")
}
defer resp.Body.Close()
defer client.CloseIdleConnections()
if resp.StatusCode != 200 {
glog.Errorln("response error [Get LoginInfo]!")
glog.Errorln("response status code: %d, %s", resp.StatusCode, resp.Body)
return nil, errors.NewBusinessError(errors.ServerError, "response error [Get LoginInfo]!")
}
var respBody map[string]interface{}
respStr, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respStr, &respBody)
if err != nil {
glog.Errorln("failed to decode response [Get LoginInfo]!", err)
return nil, errors.NewBusinessError(errors.ServerError, "failed to decode response [Get LoginInfo]!")
}
data := respBody["data"]
if data == nil {
meta := respBody["meta"]
return nil, fmt.Errorf("failed to get user info from login server! %s", meta)
}
userObj := &user.UserObj{}
userMap := data.(map[string]interface{})["user"]
userId := userMap.(map[string]interface{})["userId"]
if userId != nil {
userObj.UserID = userId.(string)
}
cn := userMap.(map[string]interface{})["cn"]
if cn != nil {
userObj.DisplayName = cn.(string)
}
mobile := userMap.(map[string]interface{})["mobile"]
if mobile != nil {
userObj.Mobile = mobile.(string)
}
provinceId := userMap.(map[string]interface{})["provinceId"]
if provinceId != nil {
userObj.ProvinceId = provinceId.(string)
}
userObj.Status = userMap.(map[string]interface{})["status"].(string)
accountMap := data.(map[string]interface{})["account"]
userName := accountMap.(map[string]interface{})["loginName"]
if userName != nil {
userObj.UserName = userName.(string)
}
if userName == "admin" {
userObj.Role = 1
} else {
userObj.Role = 0
}
if config.Config.CfnConfig.Enable {
userObj.Namespace = fmt.Sprintf("DEFAULT,%s", config.Config.CfnConfig.CfnWorkSpaceId)
} else {
userObj.Namespace = "DEFAULT"
}
return userObj, nil
}