mirror of
https://gitee.com/zhangsken/aliyunpan.git
synced 2026-10-16 10:29:42 +08:00
add qrcode login api
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
package panlogin
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/library-go/crypto"
|
||||
"github.com/tickstep/library-go/getip"
|
||||
"github.com/tickstep/library-go/ids"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/tickstep/library-go/requester"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LoginHelper struct {
|
||||
webHost string
|
||||
}
|
||||
|
||||
type LoginHttpResult struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// QRCodeUrlResult 二维码登录页面
|
||||
type QRCodeUrlResult struct {
|
||||
TokenId string `json:"tokenId"`
|
||||
TokenUrl string `json:"tokenUrl"`
|
||||
ExpiredTime int `json:"expiredTime"`
|
||||
}
|
||||
|
||||
// QRCodeLoginResult 二维码登录结果
|
||||
type QRCodeLoginResult struct {
|
||||
QrCodeStatus string `json:"qrCodeStatus"`
|
||||
SecureRefreshToken string `json:"secureRefreshToken"`
|
||||
}
|
||||
|
||||
func NewLoginHelper(webHost string) *LoginHelper {
|
||||
return &LoginHelper{
|
||||
webHost: webHost,
|
||||
}
|
||||
}
|
||||
|
||||
// GetQRCodeLoginUrl 获取登录二维码链接
|
||||
func (h *LoginHelper) GetQRCodeLoginUrl(keyStr string) (*QRCodeUrlResult, error) {
|
||||
fullUrl := strings.Builder{}
|
||||
ipAddr, err := getip.IPInfoFromTechainBaidu()
|
||||
if err != nil {
|
||||
ipAddr = "127.0.0.1"
|
||||
}
|
||||
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/qrcode/create?ip=%s&os=%s&arch=%s&version=%s&key=%s",
|
||||
h.webHost, ipAddr, runtime.GOOS, runtime.GOARCH, config.AppVersion, keyStr)
|
||||
|
||||
logger.Verboseln("do request url: " + fullUrl.String())
|
||||
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(20 * time.Second)
|
||||
client.SetKeepAlive(false)
|
||||
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
|
||||
if err != nil {
|
||||
logger.Verboseln("get qr code error ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse result
|
||||
r := &LoginHttpResult{}
|
||||
r.Data = &QRCodeUrlResult{}
|
||||
if err2 := json.Unmarshal(body, r); err2 != nil {
|
||||
logger.Verboseln("parse qrcode result json error ", err2)
|
||||
return nil, err2
|
||||
}
|
||||
if r.Code != 0 {
|
||||
return nil, fmt.Errorf(r.Msg)
|
||||
}
|
||||
token := r.Data.(*QRCodeUrlResult)
|
||||
if len(token.TokenUrl) > 0 {
|
||||
u, err := url.Parse(token.TokenUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, _ := url.ParseQuery(u.RawQuery)
|
||||
token.TokenId = m["tokenId"][0]
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// GetQRCodeLoginResult 获取二维码登录结果
|
||||
func (h *LoginHelper) GetQRCodeLoginResult(tokenId string) (*QRCodeLoginResult, error) {
|
||||
fullUrl := strings.Builder{}
|
||||
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/qrcode/result?tokenId=%s",
|
||||
h.webHost, tokenId)
|
||||
|
||||
logger.Verboseln("do request url: " + fullUrl.String())
|
||||
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(20 * time.Second)
|
||||
client.SetKeepAlive(false)
|
||||
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
|
||||
if err != nil {
|
||||
logger.Verboseln("get qr code result error ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse result
|
||||
r := &LoginHttpResult{}
|
||||
r.Data = &QRCodeLoginResult{}
|
||||
if err2 := json.Unmarshal(body, r); err2 != nil {
|
||||
logger.Verboseln("parse qrcode result json error ", err2)
|
||||
return nil, err2
|
||||
}
|
||||
if r.Code != 0 {
|
||||
return nil, fmt.Errorf(r.Msg)
|
||||
}
|
||||
return r.Data.(*QRCodeLoginResult), nil
|
||||
}
|
||||
|
||||
// GetRefreshToken 获取Token
|
||||
func (h *LoginHelper) GetRefreshToken(tokenId string) (*QRCodeLoginResult, error) {
|
||||
fullUrl := strings.Builder{}
|
||||
fmt.Fprintf(&fullUrl, "%s/auth/tickstep/aliyunpan/token/qrcode/retrieve?tokenId=%s",
|
||||
h.webHost, tokenId)
|
||||
logger.Verboseln("do request url: " + fullUrl.String())
|
||||
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(20 * time.Second)
|
||||
client.SetKeepAlive(false)
|
||||
body, err := client.Fetch("GET", fullUrl.String(), nil, header)
|
||||
if err != nil {
|
||||
logger.Verboseln("get refresh token result error ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse result
|
||||
r := &LoginHttpResult{}
|
||||
r.Data = &QRCodeLoginResult{}
|
||||
if err2 := json.Unmarshal(body, r); err2 != nil {
|
||||
logger.Verboseln("parse refresh token result json error ", err2)
|
||||
return nil, err2
|
||||
}
|
||||
if r.Code != 0 {
|
||||
return nil, fmt.Errorf(r.Msg)
|
||||
}
|
||||
return r.Data.(*QRCodeLoginResult), nil
|
||||
}
|
||||
|
||||
// ParseSecureRefreshToken 解密Token
|
||||
func (h *LoginHelper) ParseSecureRefreshToken(keyStr, secureRefreshToken string) (string, error) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.Verboseln("decrypt string failed, maybe the key has been changed")
|
||||
}
|
||||
}()
|
||||
|
||||
if len(keyStr) == 0 {
|
||||
keyStr = ids.GetUniqueId("", 32)
|
||||
}
|
||||
|
||||
if secureRefreshToken == "" {
|
||||
return "", nil
|
||||
}
|
||||
d, _ := hex.DecodeString(secureRefreshToken)
|
||||
|
||||
// use the machine unique id as the key
|
||||
// but in some OS, this key will be changed if you reinstall the OS
|
||||
key := []byte(keyStr)
|
||||
if len(key) > 16 {
|
||||
key = key[:16]
|
||||
}
|
||||
r, e := crypto.DecryptAES(d, key)
|
||||
if e != nil {
|
||||
return "", nil
|
||||
}
|
||||
return string(r), nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2020 tickstep.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package panlogin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tickstep/library-go/ids"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGetQRCodeLoginUrl(t *testing.T) {
|
||||
h := NewLoginHelper("http://localhost:8977")
|
||||
keyStr := ids.GetUniqueId("", 32)
|
||||
fmt.Println(keyStr)
|
||||
r, e := h.GetQRCodeLoginUrl(keyStr)
|
||||
fmt.Println(e)
|
||||
fmt.Println(r)
|
||||
}
|
||||
|
||||
func TestGetQRCodeLoginResult(t *testing.T) {
|
||||
h := NewLoginHelper("http://localhost:8977")
|
||||
tokenId := "26e69f9978ba4574a1d66e58399fed4e"
|
||||
for {
|
||||
r, e := h.GetQRCodeLoginResult(tokenId)
|
||||
fmt.Println(e)
|
||||
fmt.Println(r)
|
||||
time.Sleep(1 * time.Second)
|
||||
if r.QrCodeStatus == "CONFIRMED" {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRefreshToken(t *testing.T) {
|
||||
h := NewLoginHelper("http://localhost:8977")
|
||||
tokenId := "26e69f9978ba4574a1d66e58399fed4e"
|
||||
r, e := h.GetRefreshToken(tokenId)
|
||||
fmt.Println(e)
|
||||
fmt.Println(r)
|
||||
}
|
||||
|
||||
func TestParseRefreshToken(t *testing.T) {
|
||||
h := NewLoginHelper("http://localhost:8977")
|
||||
secureToken := "eff6054736d47b9c31f8839465555ebdff38c878ea0abbcd4b2336b30d33c71c7dac8824e40991654429ae521d8ef471"
|
||||
r, e := h.ParseSecureRefreshToken("", secureToken)
|
||||
fmt.Println(e)
|
||||
fmt.Println(r)
|
||||
}
|
||||
Reference in New Issue
Block a user