fix: keep failed login authentication unchanged

This commit is contained in:
2026-07-22 16:09:01 +08:00
parent 12ba947f9b
commit a174a22bcb
3 changed files with 95 additions and 39 deletions
+39 -37
View File
@@ -150,26 +150,29 @@ func (client *Client) loadAuthData() error {
}
func (client *Client) ensureIdentity() {
client.updateAuthData(func(authData *AuthData) {
if authData.PassO == "" {
authData.PassO = randomString(16, "0123456789abcdef")
}
if authData.DeviceID == "" {
authData.DeviceID = randomString(16, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-")
}
if authData.UA != "" {
return
}
countryCode := "CN"
if parts := strings.Split(client.locale, "_"); len(parts) == 2 {
countryCode = parts[1]
}
id1 := randomString(40, "0123456789ABCDEF")
id2 := randomString(32, "0123456789ABCDEF")
id3 := randomString(32, "0123456789ABCDEF")
id4 := randomString(40, "0123456789ABCDEF")
authData.UA = fmt.Sprintf("Android-15-11.0.701-Xiaomi-23046RP50C-OS2.0.212.0.VMYCNXM-%s-%s-%s-%s-SmartHome-MI_APP_STORE-%s|%s|%s-64", id1, countryCode, id3, id2, id1, id4, authData.PassO)
})
client.setAuthData(client.authDataWithIdentity(client.AuthData()))
}
func (client *Client) authDataWithIdentity(authData AuthData) AuthData {
if authData.PassO == "" {
authData.PassO = randomString(16, "0123456789abcdef")
}
if authData.DeviceID == "" {
authData.DeviceID = randomString(16, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-")
}
if authData.UA != "" {
return authData
}
countryCode := "CN"
if parts := strings.Split(client.locale, "_"); len(parts) == 2 {
countryCode = parts[1]
}
id1 := randomString(40, "0123456789ABCDEF")
id2 := randomString(32, "0123456789ABCDEF")
id3 := randomString(32, "0123456789ABCDEF")
id4 := randomString(40, "0123456789ABCDEF")
authData.UA = fmt.Sprintf("Android-15-11.0.701-Xiaomi-23046RP50C-OS2.0.212.0.VMYCNXM-%s-%s-%s-%s-SmartHome-MI_APP_STORE-%s|%s|%s-64", id1, countryCode, id3, id2, id1, id4, authData.PassO)
return authData
}
func randomString(length int, alphabet string) string {
@@ -318,9 +321,9 @@ func (value *stringOrNumber) UnmarshalJSON(payload []byte) error {
func (client *Client) Login(ctx context.Context) (AuthData, error) {
client.loginMu.Lock()
defer client.loginMu.Unlock()
client.ensureIdentity()
candidate := client.authDataWithIdentity(client.AuthData())
location, refreshedAuthData, err := client.getLocation(ctx)
location, refreshedAuthData, err := client.getLocation(ctx, candidate)
if err != nil {
return AuthData{}, err
}
@@ -330,7 +333,7 @@ func (client *Client) Login(ctx context.Context) (AuthData, error) {
}
return client.AuthData(), nil
}
loginData, err := client.getQRLoginData(ctx, location)
loginData, err := client.getQRLoginData(ctx, location, candidate)
if err != nil {
return AuthData{}, err
}
@@ -352,10 +355,10 @@ func (client *Client) Login(ctx context.Context) (AuthData, error) {
}
}
}
return client.completeQRLogin(ctx, loginData)
return client.completeQRLogin(ctx, loginData, candidate)
}
func (client *Client) getLocation(ctx context.Context) (url.Values, *AuthData, error) {
func (client *Client) getLocation(ctx context.Context, authData AuthData) (url.Values, *AuthData, error) {
httpClient := client.newSession()
serviceURL, err := url.Parse(client.serviceLoginURL)
if err != nil {
@@ -370,7 +373,7 @@ func (client *Client) getLocation(ctx context.Context) (url.Values, *AuthData, e
if err != nil {
return nil, nil, err
}
client.setLoginHeaders(request, true)
client.setLoginHeaders(request, authData, true)
var data serviceLoginData
if err := client.doLoginRequestWithClient(httpClient, request, false, &data); err != nil {
return nil, nil, err
@@ -383,7 +386,7 @@ func (client *Client) getLocation(ctx context.Context) (url.Values, *AuthData, e
if err != nil {
return nil, nil, err
}
client.setLoginHeaders(refreshRequest, false)
client.setLoginHeaders(refreshRequest, authData, false)
response, err := httpClient.Do(refreshRequest)
if err != nil {
return nil, nil, fmt.Errorf("refresh login token: %w", err)
@@ -399,7 +402,7 @@ func (client *Client) getLocation(ctx context.Context) (url.Values, *AuthData, e
if string(body) != "ok" {
return nil, nil, &LoginError{Code: -1, Message: string(body)}
}
candidate := client.AuthData()
candidate := authData
serviceTokenReceived := updateAuthDataFromCookies(&candidate, httpClient, response.Request.URL)
candidate.Ssecurity = data.Ssecurity
if !serviceTokenReceived || !candidate.complete() {
@@ -415,7 +418,7 @@ func (client *Client) getLocation(ctx context.Context) (url.Values, *AuthData, e
return locationURL.Query(), nil, nil
}
func (client *Client) getQRLoginData(ctx context.Context, location url.Values) (qrLoginData, error) {
func (client *Client) getQRLoginData(ctx context.Context, location url.Values, authData AuthData) (qrLoginData, error) {
location.Set("theme", "")
location.Set("bizDeviceType", "")
location.Set("_hasLogo", "false")
@@ -430,7 +433,7 @@ func (client *Client) getQRLoginData(ctx context.Context, location url.Values) (
if err != nil {
return qrLoginData{}, err
}
client.setLoginHeaders(request, false)
client.setLoginHeaders(request, authData, false)
var data qrLoginData
if err := client.doLoginRequest(request, true, &data); err != nil {
return qrLoginData{}, err
@@ -441,7 +444,7 @@ func (client *Client) getQRLoginData(ctx context.Context, location url.Values) (
return data, nil
}
func (client *Client) completeQRLogin(ctx context.Context, loginData qrLoginData) (AuthData, error) {
func (client *Client) completeQRLogin(ctx context.Context, loginData qrLoginData, authData AuthData) (AuthData, error) {
pollContext, cancel := context.WithTimeout(ctx, qrLoginTimeout)
defer cancel()
httpClient := client.newSession()
@@ -449,7 +452,7 @@ func (client *Client) completeQRLogin(ctx context.Context, loginData qrLoginData
if err != nil {
return AuthData{}, err
}
client.setLoginHeaders(request, false)
client.setLoginHeaders(request, authData, false)
var data longPollData
if err := client.doLoginRequestWithClient(httpClient, request, true, &data); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
@@ -461,7 +464,7 @@ func (client *Client) completeQRLogin(ctx context.Context, loginData qrLoginData
if err != nil {
return AuthData{}, err
}
client.setLoginHeaders(callback, false)
client.setLoginHeaders(callback, authData, false)
response, err := httpClient.Do(callback)
if err != nil {
return AuthData{}, fmt.Errorf("complete login callback: %w", err)
@@ -474,7 +477,7 @@ func (client *Client) completeQRLogin(ctx context.Context, loginData qrLoginData
if response.StatusCode < 200 || response.StatusCode >= 300 {
return AuthData{}, &LoginError{Code: response.StatusCode, Message: "登录回调失败"}
}
candidate := client.AuthData()
candidate := authData
candidate.Ssecurity = ""
candidate.UserID = ""
candidate.CUserID = ""
@@ -530,8 +533,7 @@ func (client *Client) doLoginRequestWithClient(httpClient *http.Client, request
return nil
}
func (client *Client) setLoginHeaders(request *http.Request, withCookies bool) {
authData := client.AuthData()
func (client *Client) setLoginHeaders(request *http.Request, authData AuthData, withCookies bool) {
request.Header.Set("User-Agent", authData.UA)
request.Header.Set("Connection", "keep-alive")
request.Header.Set("Accept-Encoding", "gzip")
@@ -583,7 +585,7 @@ func (client *Client) refreshToken(ctx context.Context) error {
if available {
return nil
}
_, refreshedAuthData, err := client.getLocation(ctx)
_, refreshedAuthData, err := client.getLocation(ctx, client.AuthData())
if err != nil {
return err
}