197 lines
5.8 KiB
Go
197 lines
5.8 KiB
Go
package login
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"likedream-goframe/internal/application/cookiejar"
|
|
"likedream-goframe/internal/application/cpdaily/school"
|
|
"likedream-goframe/internal/application/httpclient"
|
|
"likedream-goframe/internal/common/errors"
|
|
"likedream-goframe/internal/ent/cpuser"
|
|
"likedream-goframe/internal/framework/logger"
|
|
"likedream-goframe/internal/utils"
|
|
"strings"
|
|
|
|
"github.com/samber/oops"
|
|
"go.uber.org/zap"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
func ActivateSession(ctx context.Context, host string, client *resty.Client) {
|
|
// 处理cookie,干掉path
|
|
jar := client.CookieJar()
|
|
realJar := jar.(*cookiejar.PersistCookieJar)
|
|
realJar.RemoveCookieInfo()
|
|
client.SetCookieJar(realJar)
|
|
client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20))
|
|
|
|
host = strings.TrimSuffix(host, "/")
|
|
|
|
activateStep1 := func() {
|
|
sessionResponse, err := client.R().
|
|
WithContext(ctx).
|
|
Get(fmt.Sprintf("%s/wec-im-group/group/groupMember/checkImInitFlag", host))
|
|
|
|
utils.OkOrPanic(err)
|
|
|
|
defer sessionResponse.Body.Close()
|
|
|
|
if !sessionResponse.IsSuccess() && sessionResponse.StatusCode() != 502 {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "Session激活失败"),
|
|
func(err error) error {
|
|
return oops.
|
|
WithContext(ctx).
|
|
With("host", host).
|
|
Wrap(err)
|
|
})
|
|
}
|
|
}
|
|
|
|
activateStep2 := func() {
|
|
sessionResponse, err := client.R().
|
|
WithContext(ctx).
|
|
SetBody(map[string]any{}).
|
|
Post(fmt.Sprintf("%s/wec-counselor-attendance-apps/student/attendance/getStuSignInfosByWeekMonth", host))
|
|
|
|
utils.OkOrPanic(err)
|
|
|
|
defer sessionResponse.Body.Close()
|
|
|
|
if !sessionResponse.IsSuccess() {
|
|
if sessionResponse.StatusCode() == 405 {
|
|
return
|
|
}
|
|
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "Session激活失败"),
|
|
func(err error) error {
|
|
return oops.
|
|
WithContext(ctx).
|
|
With("host", host).
|
|
Wrap(err)
|
|
})
|
|
}
|
|
|
|
responseContentType := sessionResponse.Header().Get("Content-Type")
|
|
if !strings.Contains(responseContentType, "json") {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "Session激活失败"),
|
|
func(err error) error {
|
|
return oops.
|
|
WithContext(ctx).
|
|
With("host", host).
|
|
With("response_content_type", responseContentType).
|
|
Wrap(err)
|
|
})
|
|
}
|
|
}
|
|
|
|
activateStep1()
|
|
activateStep2()
|
|
|
|
client.SetRedirectPolicy(resty.NoRedirectPolicy())
|
|
}
|
|
|
|
func CookieEnabled(ctx context.Context, host string, client *resty.Client, loginType cpuser.LoginType) bool {
|
|
client.SetRedirectPolicy(resty.NoRedirectPolicy())
|
|
host = strings.TrimSuffix(host, "/")
|
|
sessionResponse, err := client.R().
|
|
WithContext(ctx).
|
|
SetBody(map[string]any{}).
|
|
Post(fmt.Sprintf("%s/wec-counselor-attendance-apps/student/attendance/getStuAttendacesInOneDay", host))
|
|
|
|
utils.OkOrPanic(err)
|
|
needLogin := sessionResponse.StatusCode() == 302
|
|
return !needLogin
|
|
}
|
|
|
|
// RefreshCookieParams 刷新 cookie 所需的用户参数
|
|
type RefreshCookieParams struct {
|
|
ID int64
|
|
Cookie string
|
|
Tgc string
|
|
LoginType cpuser.LoginType
|
|
Username string
|
|
Password string
|
|
SchoolID string
|
|
}
|
|
|
|
// RefreshCookieResult 刷新 cookie 的结果
|
|
type RefreshCookieResult struct {
|
|
Client *resty.Client
|
|
Cookie string
|
|
Tgc string
|
|
}
|
|
|
|
// EnsureCookieValid 检测 cookie 是否过期,过期则自动刷新。
|
|
// phone 类型用 TGC 刷新,account 类型用账号密码重新登录。
|
|
func EnsureCookieValid(ctx context.Context, params *RefreshCookieParams, schoolDetail *school.SchoolDetailInfo) *RefreshCookieResult {
|
|
client := GetClient(ctx, params.Cookie)
|
|
if CookieEnabled(ctx, schoolDetail.WecloudUrl, client, params.LoginType) {
|
|
logger.Logger.Info("[TGC] cookie有效,无需刷新",
|
|
zap.Int64("userId", params.ID),
|
|
zap.String("loginType", string(params.LoginType)),
|
|
)
|
|
return &RefreshCookieResult{Client: client, Cookie: params.Cookie, Tgc: params.Tgc}
|
|
}
|
|
|
|
logger.Logger.Info("[TGC] cookie已失效,开始刷新",
|
|
zap.Int64("userId", params.ID),
|
|
zap.String("loginType", string(params.LoginType)),
|
|
zap.Bool("tgcEmpty", params.Tgc == ""),
|
|
)
|
|
|
|
var newCookie, newTgc string
|
|
|
|
if params.LoginType == cpuser.LoginTypePhone {
|
|
if params.Tgc == "" {
|
|
utils.OkOrPanic(errors.NewBusinessError(500, "TGC为空,请重新通过短信验证码登录"))
|
|
}
|
|
smsHandler := NewSmsWithoutDeviceID()
|
|
newCookie, newTgc = smsHandler.RefreshByTgc(ctx, params.Tgc, params.SchoolID)
|
|
logger.Logger.Info("[TGC] RefreshByTgc完成",
|
|
zap.Int64("userId", params.ID),
|
|
zap.Bool("cookieChanged", newCookie != params.Cookie),
|
|
)
|
|
} else {
|
|
loginExecutor := GetCpdailyLoginBySchoolInfo(ctx, schoolDetail)
|
|
loginExecutor.Login(ctx, schoolDetail, params.Username, params.Password)
|
|
newCookie = loginExecutor.GetCookieString()
|
|
newTgc = params.Tgc
|
|
}
|
|
|
|
return &RefreshCookieResult{
|
|
Client: GetClient(ctx, newCookie),
|
|
Cookie: newCookie,
|
|
Tgc: newTgc,
|
|
}
|
|
}
|
|
|
|
func GetClient(ctx context.Context, cookie string) *resty.Client {
|
|
cookieJar := cookiejar.NewPersistCookieJar()
|
|
cookieJar.Deserialize(cookie)
|
|
// 不使用 Clone,创建全新的独立 client 实例避免状态共享
|
|
client := httpclient.NewCpdailyClient()
|
|
client.SetCookieJar(cookieJar)
|
|
return client
|
|
}
|
|
|
|
func SendDynamicCodeByPhone(ctx context.Context, username string, host string, client *resty.Client) {
|
|
host = strings.TrimSuffix(host, "/")
|
|
response, err := client.R().
|
|
WithContext(ctx).
|
|
SetFormData(map[string]string{
|
|
"userName": username,
|
|
"authCodeTypeName": "reAuthDynamicCodeType",
|
|
}).
|
|
Post(fmt.Sprintf("%s/authserver/dynamicCode/getDynamicCodeByReauth.do", host))
|
|
utils.OkOrPanic(err, func(err error) error {
|
|
return oops.
|
|
In("多因子短信发送").
|
|
With("username", username).
|
|
Wrap(err)
|
|
})
|
|
responseJson := utils.ReadGjsonResult(response.Body)
|
|
if responseJson.Get("res").String() != "success" {
|
|
utils.OkOrPanic(errors.NewBusinessError(500, "多因子短信发送失败,原因是"+responseJson.Get("returnMessage").String()))
|
|
}
|
|
}
|