From 077a5259615a7a6a8e08bae622c8142d80809e14 Mon Sep 17 00:00:00 2001 From: Andy Hsu Date: Sat, 13 May 2023 17:26:32 +0800 Subject: [PATCH] fix(189): adapt new login method (close #4378) --- drivers/189/driver.go | 2 +- drivers/189/login.go | 126 +++++++++++++++++++++++ drivers/189/meta.go | 2 + drivers/189/util.go | 229 +++++++++++++++++++++--------------------- 4 files changed, 242 insertions(+), 117 deletions(-) create mode 100644 drivers/189/login.go diff --git a/drivers/189/driver.go b/drivers/189/driver.go index b90d0872..6fc49326 100644 --- a/drivers/189/driver.go +++ b/drivers/189/driver.go @@ -32,7 +32,7 @@ func (d *Cloud189) GetAddition() driver.Additional { func (d *Cloud189) Init(ctx context.Context) error { d.client = base.NewRestyClient(). SetHeader("Referer", "https://cloud.189.cn/") - return d.login() + return d.newLogin() } func (d *Cloud189) Drop(ctx context.Context) error { diff --git a/drivers/189/login.go b/drivers/189/login.go new file mode 100644 index 00000000..0fcec19a --- /dev/null +++ b/drivers/189/login.go @@ -0,0 +1,126 @@ +package _189 + +import ( + "errors" + "strconv" + + "github.com/alist-org/alist/v3/pkg/utils" + log "github.com/sirupsen/logrus" +) + +type AppConf struct { + Data struct { + AccountType string `json:"accountType"` + AgreementCheck string `json:"agreementCheck"` + AppKey string `json:"appKey"` + ClientType int `json:"clientType"` + IsOauth2 bool `json:"isOauth2"` + LoginSort string `json:"loginSort"` + MailSuffix string `json:"mailSuffix"` + PageKey string `json:"pageKey"` + ParamId string `json:"paramId"` + RegReturnUrl string `json:"regReturnUrl"` + ReqId string `json:"reqId"` + ReturnUrl string `json:"returnUrl"` + ShowFeedback string `json:"showFeedback"` + ShowPwSaveName string `json:"showPwSaveName"` + ShowQrSaveName string `json:"showQrSaveName"` + ShowSmsSaveName string `json:"showSmsSaveName"` + Sso string `json:"sso"` + } `json:"data"` + Msg string `json:"msg"` + Result string `json:"result"` +} + +type EncryptConf struct { + Result int `json:"result"` + Data struct { + UpSmsOn string `json:"upSmsOn"` + Pre string `json:"pre"` + PreDomain string `json:"preDomain"` + PubKey string `json:"pubKey"` + } `json:"data"` +} + +func (d *Cloud189) newLogin() error { + url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action" + res, err := d.client.R().Get(url) + if err != nil { + return err + } + // Is logged in + redirectURL := res.RawResponse.Request.URL + if redirectURL.String() == "https://cloud.189.cn/web/main" { + return nil + } + lt := redirectURL.Query().Get("lt") + reqId := redirectURL.Query().Get("reqId") + appId := redirectURL.Query().Get("appId") + headers := map[string]string{ + "lt": lt, + "reqid": reqId, + "referer": redirectURL.String(), + "origin": "https://open.e.189.cn", + } + // get app Conf + var appConf AppConf + res, err = d.client.R().SetHeaders(headers).SetFormData(map[string]string{ + "version": "2.0", + "appKey": appId, + }).SetResult(&appConf).Post("https://open.e.189.cn/api/logbox/oauth2/appConf.do") + if err != nil { + return err + } + log.Debugf("189 AppConf resp body: %s", res.String()) + if appConf.Result != "0" { + return errors.New(appConf.Msg) + } + // get encrypt conf + var encryptConf EncryptConf + res, err = d.client.R().SetHeaders(headers).SetFormData(map[string]string{ + "appId": appId, + }).Post("https://open.e.189.cn/api/logbox/config/encryptConf.do") + if err != nil { + return err + } + err = utils.Json.Unmarshal(res.Body(), &encryptConf) + if err != nil { + return err + } + log.Debugf("189 EncryptConf resp body: %s\n%+v", res.String(), encryptConf) + if encryptConf.Result != 0 { + return errors.New("get EncryptConf error:" + res.String()) + } + // TODO: getUUID? needcaptcha + // login + loginData := map[string]string{ + "version": "v2.0", + "apToken": "", + "appKey": appId, + "accountType": appConf.Data.AccountType, + "userName": encryptConf.Data.Pre + RsaEncode([]byte(d.Username), encryptConf.Data.PubKey, true), + "epd": encryptConf.Data.Pre + RsaEncode([]byte(d.Password), encryptConf.Data.PubKey, true), + "captchaType": "", + "validateCode": "", + "smsValidateCode": "", + "captchaToken": "", + "returnUrl": appConf.Data.ReturnUrl, + "mailSuffix": appConf.Data.MailSuffix, + "dynamicCheck": "FALSE", + "clientType": strconv.Itoa(appConf.Data.ClientType), + "cb_SaveName": "3", + "isOauth2": strconv.FormatBool(appConf.Data.IsOauth2), + "state": "", + "paramId": appConf.Data.ParamId, + } + res, err = d.client.R().SetHeaders(headers).SetFormData(loginData).Post("https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do") + if err != nil { + return err + } + log.Debugf("189 login resp body: %s", res.String()) + loginResult := utils.Json.Get(res.Body(), "result").ToInt() + if loginResult != 0 { + return errors.New(utils.Json.Get(res.Body(), "msg").ToString()) + } + return nil +} diff --git a/drivers/189/meta.go b/drivers/189/meta.go index dd781816..ad621fb4 100644 --- a/drivers/189/meta.go +++ b/drivers/189/meta.go @@ -8,6 +8,7 @@ import ( type Addition struct { Username string `json:"username" required:"true"` Password string `json:"password" required:"true"` + Cookie string `json:"cookie" help:"Fill in the cookie if need captcha"` driver.RootID } @@ -15,6 +16,7 @@ var config = driver.Config{ Name: "189Cloud", LocalSort: true, DefaultRoot: "-11", + Alert: `info|You can try to use 189PC driver if this driver does not work.`, } func init() { diff --git a/drivers/189/util.go b/drivers/189/util.go index 6b0ee7bd..4ae1e9df 100644 --- a/drivers/189/util.go +++ b/drivers/189/util.go @@ -11,16 +11,13 @@ import ( "io" "math" "net/http" - "regexp" "strconv" "strings" "time" "github.com/alist-org/alist/v3/drivers/base" - "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/internal/setting" "github.com/alist-org/alist/v3/pkg/utils" myrand "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/go-resty/resty/v2" @@ -30,118 +27,118 @@ import ( // do others that not defined in Driver interface -func (d *Cloud189) login() error { - url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action" - b := "" - lt := "" - ltText := regexp.MustCompile(`lt = "(.+?)"`) - var res *resty.Response - var err error - for i := 0; i < 3; i++ { - res, err = d.client.R().Get(url) - if err != nil { - return err - } - // 已经登陆 - if res.RawResponse.Request.URL.String() == "https://cloud.189.cn/web/main" { - return nil - } - b = res.String() - ltTextArr := ltText.FindStringSubmatch(b) - if len(ltTextArr) > 0 { - lt = ltTextArr[1] - break - } else { - <-time.After(time.Second) - } - } - if lt == "" { - return fmt.Errorf("get page: %s \nstatus: %d \nrequest url: %s\nredirect url: %s", - b, res.StatusCode(), res.RawResponse.Request.URL.String(), res.Header().Get("location")) - } - captchaToken := regexp.MustCompile(`captchaToken' value='(.+?)'`).FindStringSubmatch(b)[1] - returnUrl := regexp.MustCompile(`returnUrl = '(.+?)'`).FindStringSubmatch(b)[1] - paramId := regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(b)[1] - //reqId := regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(b)[1] - jRsakey := regexp.MustCompile(`j_rsaKey" value="(\S+)"`).FindStringSubmatch(b)[1] - vCodeID := regexp.MustCompile(`picCaptcha\.do\?token\=([A-Za-z0-9\&\=]+)`).FindStringSubmatch(b)[1] - vCodeRS := "" - if vCodeID != "" { - // need ValidateCode - log.Debugf("try to identify verification codes") - timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10) - u := "https://open.e.189.cn/api/logbox/oauth2/picCaptcha.do?token=" + vCodeID + timeStamp - imgRes, err := d.client.R().SetHeaders(map[string]string{ - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/76.0", - "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do", - "Sec-Fetch-Dest": "image", - "Sec-Fetch-Mode": "no-cors", - "Sec-Fetch-Site": "same-origin", - }).Get(u) - if err != nil { - return err - } - // Enter the verification code manually - //err = message.GetMessenger().WaitSend(message.Message{ - // Type: "image", - // Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(imgRes.Body()), - //}, 10) - //if err != nil { - // return err - //} - //vCodeRS, err = message.GetMessenger().WaitReceive(30) - // use ocr api - vRes, err := base.RestyClient.R().SetMultipartField( - "image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())). - Post(setting.GetStr(conf.OcrApi)) - if err != nil { - return err - } - if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 { - return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString()) - } - vCodeRS = jsoniter.Get(vRes.Body(), "result").ToString() - log.Debugln("code: ", vCodeRS) - } - userRsa := RsaEncode([]byte(d.Username), jRsakey, true) - passwordRsa := RsaEncode([]byte(d.Password), jRsakey, true) - url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do" - var loginResp LoginResp - res, err = d.client.R(). - SetHeaders(map[string]string{ - "lt": lt, - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", - "Referer": "https://open.e.189.cn/", - "accept": "application/json;charset=UTF-8", - }).SetFormData(map[string]string{ - "appKey": "cloud", - "accountType": "01", - "userName": "{RSA}" + userRsa, - "password": "{RSA}" + passwordRsa, - "validateCode": vCodeRS, - "captchaToken": captchaToken, - "returnUrl": returnUrl, - "mailSuffix": "@pan.cn", - "paramId": paramId, - "clientType": "10010", - "dynamicCheck": "FALSE", - "cb_SaveName": "1", - "isOauth2": "false", - }).Post(url) - if err != nil { - return err - } - err = utils.Json.Unmarshal(res.Body(), &loginResp) - if err != nil { - log.Error(err.Error()) - return err - } - if loginResp.Result != 0 { - return fmt.Errorf(loginResp.Msg) - } - _, err = d.client.R().Get(loginResp.ToUrl) - return err -} +//func (d *Cloud189) login() error { +// url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action" +// b := "" +// lt := "" +// ltText := regexp.MustCompile(`lt = "(.+?)"`) +// var res *resty.Response +// var err error +// for i := 0; i < 3; i++ { +// res, err = d.client.R().Get(url) +// if err != nil { +// return err +// } +// // 已经登陆 +// if res.RawResponse.Request.URL.String() == "https://cloud.189.cn/web/main" { +// return nil +// } +// b = res.String() +// ltTextArr := ltText.FindStringSubmatch(b) +// if len(ltTextArr) > 0 { +// lt = ltTextArr[1] +// break +// } else { +// <-time.After(time.Second) +// } +// } +// if lt == "" { +// return fmt.Errorf("get page: %s \nstatus: %d \nrequest url: %s\nredirect url: %s", +// b, res.StatusCode(), res.RawResponse.Request.URL.String(), res.Header().Get("location")) +// } +// captchaToken := regexp.MustCompile(`captchaToken' value='(.+?)'`).FindStringSubmatch(b)[1] +// returnUrl := regexp.MustCompile(`returnUrl = '(.+?)'`).FindStringSubmatch(b)[1] +// paramId := regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(b)[1] +// //reqId := regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(b)[1] +// jRsakey := regexp.MustCompile(`j_rsaKey" value="(\S+)"`).FindStringSubmatch(b)[1] +// vCodeID := regexp.MustCompile(`picCaptcha\.do\?token\=([A-Za-z0-9\&\=]+)`).FindStringSubmatch(b)[1] +// vCodeRS := "" +// if vCodeID != "" { +// // need ValidateCode +// log.Debugf("try to identify verification codes") +// timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10) +// u := "https://open.e.189.cn/api/logbox/oauth2/picCaptcha.do?token=" + vCodeID + timeStamp +// imgRes, err := d.client.R().SetHeaders(map[string]string{ +// "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/76.0", +// "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do", +// "Sec-Fetch-Dest": "image", +// "Sec-Fetch-Mode": "no-cors", +// "Sec-Fetch-Site": "same-origin", +// }).Get(u) +// if err != nil { +// return err +// } +// // Enter the verification code manually +// //err = message.GetMessenger().WaitSend(message.Message{ +// // Type: "image", +// // Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(imgRes.Body()), +// //}, 10) +// //if err != nil { +// // return err +// //} +// //vCodeRS, err = message.GetMessenger().WaitReceive(30) +// // use ocr api +// vRes, err := base.RestyClient.R().SetMultipartField( +// "image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())). +// Post(setting.GetStr(conf.OcrApi)) +// if err != nil { +// return err +// } +// if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 { +// return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString()) +// } +// vCodeRS = jsoniter.Get(vRes.Body(), "result").ToString() +// log.Debugln("code: ", vCodeRS) +// } +// userRsa := RsaEncode([]byte(d.Username), jRsakey, true) +// passwordRsa := RsaEncode([]byte(d.Password), jRsakey, true) +// url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do" +// var loginResp LoginResp +// res, err = d.client.R(). +// SetHeaders(map[string]string{ +// "lt": lt, +// "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", +// "Referer": "https://open.e.189.cn/", +// "accept": "application/json;charset=UTF-8", +// }).SetFormData(map[string]string{ +// "appKey": "cloud", +// "accountType": "01", +// "userName": "{RSA}" + userRsa, +// "password": "{RSA}" + passwordRsa, +// "validateCode": vCodeRS, +// "captchaToken": captchaToken, +// "returnUrl": returnUrl, +// "mailSuffix": "@pan.cn", +// "paramId": paramId, +// "clientType": "10010", +// "dynamicCheck": "FALSE", +// "cb_SaveName": "1", +// "isOauth2": "false", +// }).Post(url) +// if err != nil { +// return err +// } +// err = utils.Json.Unmarshal(res.Body(), &loginResp) +// if err != nil { +// log.Error(err.Error()) +// return err +// } +// if loginResp.Result != 0 { +// return fmt.Errorf(loginResp.Msg) +// } +// _, err = d.client.R().Get(loginResp.ToUrl) +// return err +//} func (d *Cloud189) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { var e Error @@ -163,7 +160,7 @@ func (d *Cloud189) request(url string, method string, callback base.ReqCallback, //log.Debug(res.String()) if e.ErrorCode != "" { if e.ErrorCode == "InvalidSessionKey" { - err = d.login() + err = d.newLogin() if err != nil { return nil, err }