package outServer import ( "bytes" "fmt" "io" "io/ioutil" "log" "net/http" "net/http/cookiejar" "net/url" "regexp" "strings" "sync" "time" "app.yhyue.com/moapp/jybase/common" "bp.jydev.jianyu360.cn/BaseService/gateway/core/router" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/gconv" "golang.org/x/net/publicsuffix" ) type sussBi struct { addr string loginAddr string user string pwd string Url *url.URL cookiePath string lastLogin time.Time loginLock *sync.RWMutex jar *cookiejar.Jar succbiJar *cookiejar.Jar prm *ParamReplaceManager singlePointUrl *regexp.Regexp } // 参数替换 type ParamReplace struct { Replace []ParamReplaceSetting Match []ParamReplaceSetting } type ParamReplaceSetting struct { Key, Value string } type ParamReplaceManager struct { eqRouters map[string]*ParamReplace regexRouter map[*regexp.Regexp]*ParamReplace } func InitSussBi(config map[string]interface{}) (*sussBi, error) { address := gconv.String(config["addr"]) user := gconv.String(config["user"]) password := gconv.String(config["password"]) paramReplace := gconv.Map(config["paramReplace"]) cookiePath := gconv.String(config["cookiePath"]) loginAddr := gconv.String(config["loginAddr"]) if address == "" { return nil, fmt.Errorf("配置异常") } sussCookie, err := cookiejar.New(&cookiejar.Options{ PublicSuffixList: publicsuffix.List, }) if err != nil { return nil, fmt.Errorf("初始化cookie异常") } sussCookie2, err2 := cookiejar.New(&cookiejar.Options{ PublicSuffixList: publicsuffix.List, }) if err2 != nil { return nil, fmt.Errorf("初始化cookie异常") } prManager := &ParamReplaceManager{ eqRouters: map[string]*ParamReplace{}, regexRouter: map[*regexp.Regexp]*ParamReplace{}, } for url, setting := range paramReplace { pr := &ParamReplace{} settingMap := gconv.Map(setting) if settingMap == nil || len(settingMap) == 0 { continue } if replaceMap := gconv.Map(settingMap["replace"]); replaceMap != nil && len(replaceMap) > 0 { for k, v := range replaceMap { pr.Replace = append(pr.Replace, ParamReplaceSetting{ Key: k, Value: gconv.String(v), }) } } replaceMap := gconv.Map(settingMap["match"]) if replaceMap != nil && len(replaceMap) > 0 { for k, v := range replaceMap { pr.Match = append(pr.Match, ParamReplaceSetting{ Key: k, Value: gconv.String(v), }) } } if len(pr.Match) == 0 && len(pr.Replace) == 0 { continue } if regexp.QuoteMeta(url) == url { prManager.eqRouters[url] = pr } else { if reg, err := regexp.Compile(url); err == nil { prManager.regexRouter[reg] = pr } } } u, _ := url.Parse(address) return &sussBi{ addr: address, user: user, Url: u, pwd: password, loginAddr: loginAddr, cookiePath: cookiePath, jar: sussCookie, lastLogin: time.Now(), loginLock: &sync.RWMutex{}, succbiJar: sussCookie2, prm: prManager, singlePointUrl: regexp.MustCompile(gconv.String(config["singlePointUrl"])), }, nil } // AutoLogin 自动登录 func (s *sussBi) AutoLogin() error { s.loginLock.Lock() defer s.loginLock.Unlock() if time.Now().Sub(s.lastLogin).Seconds() > 60 { client := &http.Client{ Jar: s.succbiJar, } resp, err := client.Get(fmt.Sprintf("%s/succbi/?:user=%s&:password=%s", s.addr, s.user, s.pwd)) if err != nil { return err } if !(resp.StatusCode == 302 || resp.StatusCode == 200) { return fmt.Errorf("自动登录异常") } s.succbiJar = s.jar s.lastLogin = time.Now() } return nil } // RequestLogin 装配登录状态 func (s *sussBi) RequestLogin(r *ghttp.Request) error { if s.singlePointUrl.MatchString(r.RequestURI) { ctx := router.GetGContext(r.GetCtx()) md5Val := common.GetMd5String(fmt.Sprintf("%s_%s_%d_%d_%d_%d_%d_%d_%s_%d_%s_%d", ctx.Sess.NickName, ctx.Sess.YyName, ctx.Sess.EntRole, ctx.Sess.EntNicheDis, ctx.Sess.PositionId, ctx.Sess.AccountId, ctx.Sess.EntAccountId, ctx.Sess.EntId, ctx.Sess.EntName, ctx.Sess.EntDeptId, ctx.Sess.EntUserName, ctx.Sess.EntUserId)) c := &http.Cookie{ Name: "BITOKEN", Value: md5Val, Path: "/", HttpOnly: false, MaxAge: 604800, Expires: time.Now().AddDate(0, 0, 7), } r.Request.AddCookie(c) log.Println(ctx.Sess.PositionId, "BITOKEN====", md5Val) //http.SetCookie(r.Response.ResponseWriter, c) } else { if strings.HasPrefix(r.URL.Path, "/succbi") { u, e := url.Parse(s.Url.String() + "/succbi") if e != nil { log.Println("RequestLogin url.Parse error", e) return e } log.Println("succbiJar----", u.Path, u.RequestURI(), s.succbiJar.Cookies(u)) if cookies := s.succbiJar.Cookies(u); len(cookies) > 0 { log.Println("RequestLogin AddCookie", cookies[0]) r.Request.AddCookie(cookies[0]) } } else { if cookies := s.jar.Cookies(s.Url); len(cookies) > 0 { r.Request.AddCookie(cookies[0]) } } } return nil } // CheckLoginOut 检测登录状态是否过期 func (s *sussBi) CheckLoginOut(r *ghttp.Request) bool { if r.Response.Status == 401 { return true } return false } func (s *sussBi) Filter(r *ghttp.Request) error { ctx := router.GetGContext(r.GetCtx()) if ctx.Sess.NewUid != 0 { replaceMap := map[string]interface{}{ "jyUserId": ctx.Sess.PositionId, "jyUserPositionId": ctx.Sess.PositionId, "jyUserAccountId": ctx.Sess.AccountId, "jyEntPositionId": ctx.Sess.PositionId, "jyEntAccountId": ctx.Sess.EntAccountId, "jyUserName": ctx.Sess.UserName, "jyEntName": ctx.Sess.EntName, "jyEntId": ctx.Sess.EntId, "jyEntUserName": ctx.Sess.EntUserName, "jyEntUserId": ctx.Sess.EntUserId, } if r.Request.Method == http.MethodPost { bodyBytes, err := io.ReadAll(r.Request.Body) if err != nil { return err } if len(bodyBytes) > 0 { finalBytes := bodyBytes for k, v := range replaceMap { finalBytes = bytes.ReplaceAll(finalBytes, []byte(`"`+k+`"`), []byte(`"`+fmt.Sprint(v)+`"`)) } r.ContentLength = gconv.Int64(len(finalBytes)) r.Request.Header.Set("Content-Length", fmt.Sprintf("%d", len(finalBytes))) r.Request.Body = ioutil.NopCloser(bytes.NewReader(finalBytes)) } } else if r.Request.Method == http.MethodGet { var prArr *ParamReplace if rule, ok := s.prm.eqRouters[r.URL.Path]; ok && rule != nil { prArr = rule } else { for reg, rule := range s.prm.regexRouter { if reg.MatchString(r.URL.Path) { prArr = rule break } } } if prArr != nil { if newValues, err := url.ParseQuery(r.URL.RawQuery); err == nil && len(newValues) > 0 { for _, replace := range prArr.Replace { if replace.Key != "" && replace.Value != "" && replaceMap[replace.Value] != nil { newValues[replace.Key] = []string{fmt.Sprintf("%v", replaceMap[replace.Value])} } } for _, match := range prArr.Match { if match.Key != "" && match.Value != "" { if arr := strings.Split(match.Key, "."); len(arr) == 2 && replaceMap[match.Value] != nil { if value, ok := newValues[arr[0]]; ok && len(value) > 0 { newValue := strings.ReplaceAll(value[0], arr[1], fmt.Sprintf("%v", replaceMap[match.Value])) newValues[arr[0]] = []string{newValue} } } } } r.URL.RawQuery = newValues.Encode() } } } } return nil }