fix(189): adapt new login method (close #4378)

pull/4402/head
Andy Hsu 2023-05-13 17:26:32 +08:00
parent 5be79eb26e
commit 077a525961
4 changed files with 242 additions and 117 deletions

View File

@ -32,7 +32,7 @@ func (d *Cloud189) GetAddition() driver.Additional {
func (d *Cloud189) Init(ctx context.Context) error { func (d *Cloud189) Init(ctx context.Context) error {
d.client = base.NewRestyClient(). d.client = base.NewRestyClient().
SetHeader("Referer", "https://cloud.189.cn/") SetHeader("Referer", "https://cloud.189.cn/")
return d.login() return d.newLogin()
} }
func (d *Cloud189) Drop(ctx context.Context) error { func (d *Cloud189) Drop(ctx context.Context) error {

126
drivers/189/login.go Normal file
View File

@ -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
}

View File

@ -8,6 +8,7 @@ import (
type Addition struct { type Addition struct {
Username string `json:"username" required:"true"` Username string `json:"username" required:"true"`
Password string `json:"password" required:"true"` Password string `json:"password" required:"true"`
Cookie string `json:"cookie" help:"Fill in the cookie if need captcha"`
driver.RootID driver.RootID
} }
@ -15,6 +16,7 @@ var config = driver.Config{
Name: "189Cloud", Name: "189Cloud",
LocalSort: true, LocalSort: true,
DefaultRoot: "-11", DefaultRoot: "-11",
Alert: `info|You can try to use 189PC driver if this driver does not work.`,
} }
func init() { func init() {

View File

@ -11,16 +11,13 @@ import (
"io" "io"
"math" "math"
"net/http" "net/http"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/alist-org/alist/v3/drivers/base" "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/driver"
"github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/setting"
"github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/pkg/utils"
myrand "github.com/alist-org/alist/v3/pkg/utils/random" myrand "github.com/alist-org/alist/v3/pkg/utils/random"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
@ -30,118 +27,118 @@ import (
// do others that not defined in Driver interface // do others that not defined in Driver interface
func (d *Cloud189) login() error { //func (d *Cloud189) login() error {
url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action" // url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action"
b := "" // b := ""
lt := "" // lt := ""
ltText := regexp.MustCompile(`lt = "(.+?)"`) // ltText := regexp.MustCompile(`lt = "(.+?)"`)
var res *resty.Response // var res *resty.Response
var err error // var err error
for i := 0; i < 3; i++ { // for i := 0; i < 3; i++ {
res, err = d.client.R().Get(url) // res, err = d.client.R().Get(url)
if err != nil { // if err != nil {
return err // return err
} // }
// 已经登陆 // // 已经登陆
if res.RawResponse.Request.URL.String() == "https://cloud.189.cn/web/main" { // if res.RawResponse.Request.URL.String() == "https://cloud.189.cn/web/main" {
return nil // return nil
} // }
b = res.String() // b = res.String()
ltTextArr := ltText.FindStringSubmatch(b) // ltTextArr := ltText.FindStringSubmatch(b)
if len(ltTextArr) > 0 { // if len(ltTextArr) > 0 {
lt = ltTextArr[1] // lt = ltTextArr[1]
break // break
} else { // } else {
<-time.After(time.Second) // <-time.After(time.Second)
} // }
} // }
if lt == "" { // if lt == "" {
return fmt.Errorf("get page: %s \nstatus: %d \nrequest url: %s\nredirect url: %s", // 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")) // b, res.StatusCode(), res.RawResponse.Request.URL.String(), res.Header().Get("location"))
} // }
captchaToken := regexp.MustCompile(`captchaToken' value='(.+?)'`).FindStringSubmatch(b)[1] // captchaToken := regexp.MustCompile(`captchaToken' value='(.+?)'`).FindStringSubmatch(b)[1]
returnUrl := regexp.MustCompile(`returnUrl = '(.+?)'`).FindStringSubmatch(b)[1] // returnUrl := regexp.MustCompile(`returnUrl = '(.+?)'`).FindStringSubmatch(b)[1]
paramId := regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(b)[1] // paramId := regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(b)[1]
//reqId := regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(b)[1] // //reqId := regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(b)[1]
jRsakey := regexp.MustCompile(`j_rsaKey" value="(\S+)"`).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] // vCodeID := regexp.MustCompile(`picCaptcha\.do\?token\=([A-Za-z0-9\&\=]+)`).FindStringSubmatch(b)[1]
vCodeRS := "" // vCodeRS := ""
if vCodeID != "" { // if vCodeID != "" {
// need ValidateCode // // need ValidateCode
log.Debugf("try to identify verification codes") // log.Debugf("try to identify verification codes")
timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10) // timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
u := "https://open.e.189.cn/api/logbox/oauth2/picCaptcha.do?token=" + vCodeID + timeStamp // u := "https://open.e.189.cn/api/logbox/oauth2/picCaptcha.do?token=" + vCodeID + timeStamp
imgRes, err := d.client.R().SetHeaders(map[string]string{ // 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", // "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", // "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do",
"Sec-Fetch-Dest": "image", // "Sec-Fetch-Dest": "image",
"Sec-Fetch-Mode": "no-cors", // "Sec-Fetch-Mode": "no-cors",
"Sec-Fetch-Site": "same-origin", // "Sec-Fetch-Site": "same-origin",
}).Get(u) // }).Get(u)
if err != nil { // if err != nil {
return err // return err
} // }
// Enter the verification code manually // // Enter the verification code manually
//err = message.GetMessenger().WaitSend(message.Message{ // //err = message.GetMessenger().WaitSend(message.Message{
// Type: "image", // // Type: "image",
// Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(imgRes.Body()), // // Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(imgRes.Body()),
//}, 10) // //}, 10)
//if err != nil { // //if err != nil {
// return err // // return err
//} // //}
//vCodeRS, err = message.GetMessenger().WaitReceive(30) // //vCodeRS, err = message.GetMessenger().WaitReceive(30)
// use ocr api // // use ocr api
vRes, err := base.RestyClient.R().SetMultipartField( // vRes, err := base.RestyClient.R().SetMultipartField(
"image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())). // "image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())).
Post(setting.GetStr(conf.OcrApi)) // Post(setting.GetStr(conf.OcrApi))
if err != nil { // if err != nil {
return err // return err
} // }
if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 { // if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 {
return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString()) // return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString())
} // }
vCodeRS = jsoniter.Get(vRes.Body(), "result").ToString() // vCodeRS = jsoniter.Get(vRes.Body(), "result").ToString()
log.Debugln("code: ", vCodeRS) // log.Debugln("code: ", vCodeRS)
} // }
userRsa := RsaEncode([]byte(d.Username), jRsakey, true) // userRsa := RsaEncode([]byte(d.Username), jRsakey, true)
passwordRsa := RsaEncode([]byte(d.Password), jRsakey, true) // passwordRsa := RsaEncode([]byte(d.Password), jRsakey, true)
url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do" // url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do"
var loginResp LoginResp // var loginResp LoginResp
res, err = d.client.R(). // res, err = d.client.R().
SetHeaders(map[string]string{ // SetHeaders(map[string]string{
"lt": lt, // "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", // "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/", // "Referer": "https://open.e.189.cn/",
"accept": "application/json;charset=UTF-8", // "accept": "application/json;charset=UTF-8",
}).SetFormData(map[string]string{ // }).SetFormData(map[string]string{
"appKey": "cloud", // "appKey": "cloud",
"accountType": "01", // "accountType": "01",
"userName": "{RSA}" + userRsa, // "userName": "{RSA}" + userRsa,
"password": "{RSA}" + passwordRsa, // "password": "{RSA}" + passwordRsa,
"validateCode": vCodeRS, // "validateCode": vCodeRS,
"captchaToken": captchaToken, // "captchaToken": captchaToken,
"returnUrl": returnUrl, // "returnUrl": returnUrl,
"mailSuffix": "@pan.cn", // "mailSuffix": "@pan.cn",
"paramId": paramId, // "paramId": paramId,
"clientType": "10010", // "clientType": "10010",
"dynamicCheck": "FALSE", // "dynamicCheck": "FALSE",
"cb_SaveName": "1", // "cb_SaveName": "1",
"isOauth2": "false", // "isOauth2": "false",
}).Post(url) // }).Post(url)
if err != nil { // if err != nil {
return err // return err
} // }
err = utils.Json.Unmarshal(res.Body(), &loginResp) // err = utils.Json.Unmarshal(res.Body(), &loginResp)
if err != nil { // if err != nil {
log.Error(err.Error()) // log.Error(err.Error())
return err // return err
} // }
if loginResp.Result != 0 { // if loginResp.Result != 0 {
return fmt.Errorf(loginResp.Msg) // return fmt.Errorf(loginResp.Msg)
} // }
_, err = d.client.R().Get(loginResp.ToUrl) // _, err = d.client.R().Get(loginResp.ToUrl)
return err // return err
} //}
func (d *Cloud189) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { func (d *Cloud189) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
var e Error var e Error
@ -163,7 +160,7 @@ func (d *Cloud189) request(url string, method string, callback base.ReqCallback,
//log.Debug(res.String()) //log.Debug(res.String())
if e.ErrorCode != "" { if e.ErrorCode != "" {
if e.ErrorCode == "InvalidSessionKey" { if e.ErrorCode == "InvalidSessionKey" {
err = d.login() err = d.newLogin()
if err != nil { if err != nil {
return nil, err return nil, err
} }