diff --git a/internal/command/login.go b/internal/command/login.go index 612528d..1f02b95 100644 --- a/internal/command/login.go +++ b/internal/command/login.go @@ -14,12 +14,17 @@ package command import ( + "encoding/json" "fmt" "github.com/tickstep/aliyunpan-api/aliyunpan" + "github.com/tickstep/aliyunpan-api/aliyunpan/apierror" "github.com/tickstep/aliyunpan/cmder" "github.com/tickstep/aliyunpan/internal/config" + "github.com/tickstep/library-go/logger" + "github.com/tickstep/library-go/requester" _ "github.com/tickstep/library-go/requester" "github.com/urfave/cli" + "time" ) @@ -29,20 +34,47 @@ func CmdLogin() cli.Command { Usage: "登录阿里云盘账号", Description: ` 示例: + 1.常规登录,按提示一步一步来即可 aliyunpan login + + 2.直接指定RefreshToken进行登录 aliyunpan login -RefreshToken=8B12CBBCE89CA8DFC3445985B63B511B5E7EC7... - 常规登录: - 按提示一步一步来即可. + 3.指定自行搭建的web服务,从指定的URL获取Token进行登录 + aliyunpan login --RefreshTokenUrl "http://your.host.com/aliyunpan/token/refresh" + + URL获取的响应体必须是JSON,格式要求如下所示,data内容即为token: + { + "code": "0", + "msg": "ok", + "data": "88771cd41a111521b4471a552bf633ba" + } `, Category: "阿里云盘账号", Before: cmder.ReloadConfigFunc, // 每次进行登录动作的时候需要调用刷新配置 After: cmder.SaveConfigFunc, // 登录完成需要调用保存配置 Action: func(c *cli.Context) error { + // 优先从web服务获取token + refreshTokenStr := "" + if c.String("RefreshTokenUrl") != "" { + refreshTokenUrl := c.String("RefreshTokenUrl") + ts, e := getRefreshTokenFromWebServer(refreshTokenUrl) + if e != nil { + fmt.Println("从web服务获取Token失败") + } else if ts != "" { + fmt.Println("成功从web服务获取Token:" + ts) + refreshTokenStr = ts + } + } + + if refreshTokenStr == "" { + refreshTokenStr = c.String("RefreshToken") + } + webToken := aliyunpan.WebLoginToken{} refreshToken := "" var err error - refreshToken, webToken, err = RunLogin(c.String("RefreshToken")) + refreshToken, webToken, err = RunLogin(refreshTokenStr) if err != nil { fmt.Println(err) return err @@ -63,7 +95,11 @@ func CmdLogin() cli.Command { // aliyunpan login -RefreshToken=8B12CBBCE89CA8DFC3445985B63B511B5E7EC7... cli.StringFlag{ Name: "RefreshToken", - Usage: "使用 RefreshToken Cookie来登录帐号", + Usage: "使用RefreshToken Cookie来登录帐号", + }, + cli.StringFlag{ + Name: "RefreshTokenUrl", + Usage: "使用自行搭建的web服务获取RefreshToken来进行登录", }, }, } @@ -116,3 +152,41 @@ func CmdLogout() cli.Command { func RunLogin(refreshToken string) (refreshTokenStr string, webToken aliyunpan.WebLoginToken, error error) { return cmder.DoLoginHelper(refreshToken) } + + +// getRefreshTokenFromWebServer 从自定义的web服务获取token +func getRefreshTokenFromWebServer(url string) (string, error) { + type tokenResult struct { + Code string `json:"code"` + Msg string `json:"msg"` + Data string `json:"data"` + } + + if url == "" { + return "", fmt.Errorf("url is empty") + } + + logger.Verboseln("do request url: " + url) + header := map[string]string { + "accept": "application/json, text/plain, */*", + "content-type": "application/json;charset=UTF-8", + "user-agent": "aliyunpan/" + config.AppVersion, + } + // request + client := requester.NewHTTPClient() + client.SetTimeout(10 * time.Second) + client.SetKeepAlive(false) + body, err := client.Fetch("GET", url, nil, header) + if err != nil { + logger.Verboseln("get token error ", err) + return "", err + } + + // parse result + r := &tokenResult{} + if err2 := json.Unmarshal(body, r); err2 != nil { + logger.Verboseln("parse token info result json error ", err2) + return "", apierror.NewFailedApiError(err2.Error()) + } + return r.Data, nil +}