diff --git a/cloudpan/app_login.go b/cloudpan/app_login.go index af5c646..72f6848 100644 --- a/cloudpan/app_login.go +++ b/cloudpan/app_login.go @@ -18,6 +18,7 @@ package cloudpan import ( "encoding/json" "encoding/xml" + "errors" "fmt" "github.com/tickstep/cloudpan189-api/cloudpan/apierror" "github.com/tickstep/cloudpan189-api/cloudpan/apiutil" @@ -33,59 +34,69 @@ import ( type ( appLoginParams struct { CaptchaToken string - Lt string - ReturnUrl string - ParamId string - ReqId string - jRsaKey string + Lt string + ReturnUrl string + ParamId string + ReqId string + jRsaKey string + Pre string + } + + EncryptConfData struct { + Pre string `json:"pre"` + PubKey string `json:"pubKey"` + } + EncryptConf struct { + Result int `json:"result"` + Data EncryptConfData `json:"data"` } AppLoginToken struct { - SessionKey string `json:"sessionKey"` - SessionSecret string `json:"sessionSecret"` - FamilySessionKey string `json:"familySessionKey"` + SessionKey string `json:"sessionKey"` + SessionSecret string `json:"sessionSecret"` + FamilySessionKey string `json:"familySessionKey"` FamilySessionSecret string `json:"familySessionSecret"` - AccessToken string `json:"accessToken"` - RefreshToken string `json:"refreshToken"` + AccessToken string `json:"accessToken"` + RefreshToken string `json:"refreshToken"` // 有效期的token SskAccessToken string `json:"sskAccessToken"` // token 过期时间点,时间戳ms - SskAccessTokenExpiresIn int64 `json:"sskAccessTokenExpiresIn"` - RsaPublicKey string `json:"rsaPublicKey"` + SskAccessTokenExpiresIn int64 `json:"sskAccessTokenExpiresIn"` + RsaPublicKey string `json:"rsaPublicKey"` } appSessionResp struct { - ResCode int `json:"res_code"` - ResMessage string `json:"res_message"` - AccessToken string `json:"accessToken"` - FamilySessionKey string `json:"familySessionKey"` + ResCode int `json:"res_code"` + ResMessage string `json:"res_message"` + AccessToken string `json:"accessToken"` + FamilySessionKey string `json:"familySessionKey"` FamilySessionSecret string `json:"familySessionSecret"` - GetFileDiffSpan int `json:"getFileDiffSpan"` - GetUserInfoSpan int `json:"getUserInfoSpan"` - IsSaveName string `json:"isSaveName"` - KeepAlive int `json:"keepAlive"` - LoginName string `json:"loginName"` - RefreshToken string `json:"refreshToken"` - SessionKey string `json:"sessionKey"` - SessionSecret string `json:"sessionSecret"` + GetFileDiffSpan int `json:"getFileDiffSpan"` + GetUserInfoSpan int `json:"getUserInfoSpan"` + IsSaveName string `json:"isSaveName"` + KeepAlive int `json:"keepAlive"` + LoginName string `json:"loginName"` + RefreshToken string `json:"refreshToken"` + SessionKey string `json:"sessionKey"` + SessionSecret string `json:"sessionSecret"` } accessTokenResp struct { // token过期时间,默认30天 - ExpiresIn int64 `json:"expiresIn"` + ExpiresIn int64 `json:"expiresIn"` AccessToken string `json:"accessToken"` } - + appRefreshUserSessionResp struct { - XMLName xml.Name `xml:"userSession"` - LoginName string `xml:"loginName"` - SessionKey string `xml:"sessionKey"` - SessionSecret string `xml:"sessionSecret"` - KeepAlive int `xml:"keepAlive"` - GetFileDiffSpan int `xml:"getFileDiffSpan"` - GetUserInfoSpan int `xml:"getUserInfoSpan"` - FamilySessionKey string `xml:"familySessionKey"` - FamilySessionSecret string `xml:"familySessionSecret"` + XMLName xml.Name `xml:"userSession"` + LoginName string `xml:"loginName"` + SessionKey string `xml:"sessionKey"` + SessionSecret string `xml:"sessionSecret"` + KeepAlive int `xml:"keepAlive"` + GetFileDiffSpan int `xml:"getFileDiffSpan"` + GetUserInfoSpan int `xml:"getUserInfoSpan"` + FamilySessionKey string `xml:"familySessionKey"` + FamilySessionSecret string `xml:"familySessionSecret"` } ) @@ -108,30 +119,47 @@ func AppLogin(username, password string) (result *AppLoginToken, error *apierror rsaUserName, _ := crypto.RsaEncrypt([]byte(rsaKey.String()), []byte(username)) rsaPassword, _ := crypto.RsaEncrypt([]byte(rsaKey.String()), []byte(password)) + needcaptchaMap := map[string]string{ + "accountType": "02", + "appKey": "8025431004", + "userName": loginParams.Pre + apiutil.B64toHex(string(crypto.Base64Encode(rsaUserName))), + } + needcaptchaDate, err1 := appClient.Fetch("POST", "https://open.e.189.cn/api/logbox/oauth2/needcaptcha.do", needcaptchaMap, nil) + + if err1 != nil { + logger.Verboseln("login needcaptcha occurs error: ", err1.Error()) + return nil, apierror.NewApiErrorWithError(err1) + } + needcaptchaStr := string(needcaptchaDate) + if !strings.EqualFold("0", needcaptchaStr) { + logger.Verboseln("login need captcha, stop login") + return nil, apierror.NewApiErrorWithError(errors.New("login need captcha")) + } + urlStr := "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do" - headers := map[string]string { - "Content-Type": "application/x-www-form-urlencoded", - "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do", - "Cookie": "LT=" + loginParams.Lt, + headers := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do", + "Cookie": "LT=" + loginParams.Lt, "X-Requested-With": "XMLHttpRequest", - "REQID": loginParams.ReqId, - "lt": loginParams.Lt, + "REQID": loginParams.ReqId, + "lt": loginParams.Lt, } - formData := map[string]string { - "appKey": "8025431004", - "accountType": "02", - "userName": "{RSA}" + apiutil.B64toHex(string(crypto.Base64Encode(rsaUserName))), - "password": "{RSA}" + apiutil.B64toHex(string(crypto.Base64Encode(rsaPassword))), + formData := map[string]string{ + "appKey": "8025431004", + "accountType": "02", + "userName": loginParams.Pre + apiutil.B64toHex(string(crypto.Base64Encode(rsaUserName))), + "epd": loginParams.Pre + apiutil.B64toHex(string(crypto.Base64Encode(rsaPassword))), "validateCode": "", "captchaToken": loginParams.CaptchaToken, - "returnUrl": loginParams.ReturnUrl, - "mailSuffix": "@189.cn", + "returnUrl": loginParams.ReturnUrl, + "mailSuffix": "@189.cn", "dynamicCheck": "FALSE", - "clientType": "10020", - "cb_SaveName": "1", - "isOauth2": "false", - "state": "", - "paramId": loginParams.ParamId, + "clientType": "10020", + "cb_SaveName": "0", + "isOauth2": "false", + "state": "", + "paramId": loginParams.ParamId, } logger.Verboseln("do request url: " + urlStr) @@ -153,7 +181,7 @@ func AppLogin(username, password string) (result *AppLoginToken, error *apierror fullUrl := &strings.Builder{} fmt.Fprintf(fullUrl, "%s/getSessionForPC.action?clientType=%s&version=%s&channelId=%s&redirectURL=%s", API_URL, "TELEMAC", "1.0.0", "web_cloud.189.cn", url.QueryEscape(r.ToUrl)) - headers = map[string]string { + headers = map[string]string{ "Accept": "application/json;charset=UTF-8", } logger.Verboseln("do request url: " + fullUrl.String()) @@ -183,16 +211,16 @@ func AppLogin(username, password string) (result *AppLoginToken, error *apierror fmt.Fprintf(fullUrl, "%s/open/oauth2/getAccessTokenBySsKey.action?sessionKey=%s", API_URL, rs.SessionKey) timestamp := apiutil.Timestamp() - signParams := map[string]string { - "Timestamp": strconv.Itoa(timestamp), + signParams := map[string]string{ + "Timestamp": strconv.Itoa(timestamp), "sessionKey": rs.SessionKey, - "AppKey": "601102120", + "AppKey": "601102120", } - headers = map[string]string { - "AppKey": "601102120", + headers = map[string]string{ + "AppKey": "601102120", "Signature": apiutil.SignatureOfMd5(signParams), "Sign-Type": "1", - "Accept": "application/json", + "Accept": "application/json", "Timestamp": strconv.Itoa(timestamp), } body, err1 = appClient.Fetch("GET", fullUrl.String(), nil, headers) @@ -212,12 +240,12 @@ func AppLogin(username, password string) (result *AppLoginToken, error *apierror } func appGetLoginParams() (params appLoginParams, error *apierror.ApiError) { - header := map[string]string { + header := map[string]string{ "Content-Type": "application/x-www-form-urlencoded", } fullUrl := &strings.Builder{} // use MAC client appid - fmt.Fprintf(fullUrl, "%s/unifyLoginForPC.action?appId=%s&clientType=%s&returnURL=%s&timeStamp=%d", + fmt.Fprintf(fullUrl, "%s/api/portal/unifyLoginForPC.action?appId=%s&clientType=%s&returnURL=%s&timeStamp=%d", WEB_URL, "8025431004", "10020", "https://m.cloud.189.cn/zhuanti/2020/loginErrorPc/index.html", apiutil.Timestamp()) logger.Verboseln("do request url: " + fullUrl.String()) data, err := appClient.Fetch("GET", fullUrl.String(), nil, header) @@ -242,8 +270,28 @@ func appGetLoginParams() (params appLoginParams, error *apierror.ApiError) { re, _ = regexp.Compile("reqId = \"(.+?)\"") params.ReqId = re.FindStringSubmatch(content)[1] - re, _ = regexp.Compile("j_rsaKey\" value=\"(.+?)\"") - params.jRsaKey = re.FindStringSubmatch(content)[1] + //re, _ = regexp.Compile("j_rsaKey\" value=\"(.+?)\"") + //params.jRsaKey = re.FindStringSubmatch(content)[1] + + formData := map[string]string{ + "appId": "8025431004", + } + // get rsa key + data, err = appClient.Fetch("POST", "https://open.e.189.cn/api/logbox/config/encryptConf.do", formData, header) + if err != nil { + logger.Verboseln("get encryptConf occurs error: ", err.Error()) + return params, apierror.NewApiErrorWithError(err) + } + + encryptConf := EncryptConf{} + err = json.Unmarshal(data, &encryptConf) + if err != nil { + logger.Verboseln("Unmarshal json encryptConf occurs error: ", err.Error()) + return params, apierror.NewApiErrorWithError(err) + } + params.jRsaKey = encryptConf.Data.PubKey + params.Pre = encryptConf.Data.Pre + return } @@ -252,7 +300,7 @@ func getSessionByAccessToken(accessToken string) (*appRefreshUserSessionResp, *a fullUrl := &strings.Builder{} fmt.Fprintf(fullUrl, "%s/getSessionForPC.action?appId=%s&accessToken=%s&clientSn=%s&%s", API_URL, "8025431004", accessToken, apiutil.Uuid(), apiutil.PcClientInfoSuffixParam()) - headers := map[string]string { + headers := map[string]string{ "X-Request-ID": apiutil.XRequestId(), } logger.Verboseln("do request url: " + fullUrl.String()) @@ -268,4 +316,4 @@ func getSessionByAccessToken(accessToken string) (*appRefreshUserSessionResp, *a return nil, apierror.NewApiErrorWithError(err) } return item, nil -} \ No newline at end of file +}