support login api for #207

This commit is contained in:
DismissedLight
2022-11-13 21:40:51 +08:00
parent 283df388bb
commit e29e12c9fe
8 changed files with 120 additions and 4 deletions

View File

@@ -4,6 +4,8 @@
using Microsoft.Win32;
using Snap.Hutao.Core.Convert;
using Snap.Hutao.Extension;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using System.Collections.Immutable;
using System.Text.Encodings.Web;
using Windows.ApplicationModel;
@@ -36,6 +38,11 @@ internal static class CoreEnvironment
/// </summary>
public const string DynamicSecretX6Salt = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v";
/// <summary>
/// LoginApi的盐
/// </summary>
public const string DynamicSecretPRODSalt = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS";
/// <summary>
/// 米游社请求UA
/// </summary>
@@ -46,6 +53,18 @@ internal static class CoreEnvironment
/// </summary>
public const string HoyolabXrpcVersion = "2.40.1";
/// <summary>
/// 动态密钥
/// </summary>
public static readonly ImmutableDictionary<SaltType, string> DynamicSecrets = new Dictionary<SaltType, string>()
{
[SaltType.K2] = "fdv0fY9My9eA7MR0NpjGP9RjueFvjUSQ",
[SaltType.LK2] = "jEpJb9rRARU2rXDA9qYbZ3selxkuct9a",
[SaltType.X4] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
[SaltType.X6] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
[SaltType.PROD] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS",
}.ToImmutableDictionary();
/// <summary>
/// 标准UA
/// </summary>

View File

@@ -181,6 +181,11 @@ internal static class ApiEndpoints
#region ma-cn-session
/// <summary>
/// 获取 CookieToken
/// </summary>
public const string AccountCookieAccountInfoBySToken = $"{PassportApi}/account/auth/api/getCookieAccountInfoBySToken";
/// <summary>
/// 验证 Ltoken 有效性
/// </summary>
@@ -213,6 +218,7 @@ internal static class ApiEndpoints
private const string Hk4eApiAnnouncementApi = $"{Hk4eApi}/common/hk4e_cn/announcement/api";
private const string Hk4eApiGachaInfoApi = $"{Hk4eApi}/event/gacha_info/api";
private const string PassportApi = "passport-api.mihoyo.com";
private const string PassportApiV4 = "passport-api-v4.mihoyo.com";
private const string SdkStatic = "https://sdk-static.mihoyo.com";

View File

@@ -27,7 +27,7 @@ internal abstract class DynamicSecretProvider : Md5Convert
string r = GetRandomString();
string salt = saltType == SaltType.K2 ? Core.CoreEnvironment.DynamicSecretK2Salt : Core.CoreEnvironment.DynamicSecretLK2Salt;
string salt = Core.CoreEnvironment.DynamicSecrets[saltType];
string check = ToHexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant();
return $"{t},{r},{check}";

View File

@@ -20,7 +20,7 @@ internal abstract class DynamicSecretProvider2 : Md5Convert
/// <returns>密钥</returns>
public static string Create(SaltType saltType, JsonSerializerOptions options, string queryUrl, object? postBody = null)
{
Verify.Operation(saltType is SaltType.X6 or SaltType.X4, "SALT 值无效");
Verify.Operation(saltType is SaltType.X6 or SaltType.X4 or SaltType.PROD, "SALT 值无效");
// unix timestamp
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
@@ -29,19 +29,29 @@ internal abstract class DynamicSecretProvider2 : Md5Convert
int r = GetRandom();
// body
string b = postBody is null ? string.Empty : JsonSerializer.Serialize(postBody, options);
string b = postBody is null ? GetDefaultBody(saltType) : JsonSerializer.Serialize(postBody, options);
// query
string[] queries = queryUrl.Split('?', 2);
string q = queries.Length == 2 ? string.Join('&', queries[1].Split('&').OrderBy(x => x)) : string.Empty;
// check
string salt = saltType == SaltType.X6 ? Core.CoreEnvironment.DynamicSecretX6Salt : Core.CoreEnvironment.DynamicSecretX4Salt;
string salt = Core.CoreEnvironment.DynamicSecrets[saltType];
string check = ToHexString($"salt={salt}&t={t}&r={r}&b={b}&q={q}").ToLowerInvariant();
return $"{t},{r},{check}";
}
private static string GetDefaultBody(SaltType saltType)
{
return saltType switch
{
SaltType.X4 or SaltType.X6 => string.Empty,
SaltType.PROD => "{}",
_ => throw Must.NeverHappen(((int)saltType).ToString()),
};
}
private static int GetRandom()
{
// 原汁原味

View File

@@ -23,6 +23,11 @@ public enum SaltType
/// </summary>
X6,
/// <summary>
/// PROD
/// </summary>
PROD,
/// <summary>
/// K2
/// </summary>

View File

@@ -4,6 +4,7 @@
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using Snap.Hutao.Web.Response;
using System.Net.Http;

View File

@@ -0,0 +1,53 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.Passport;
/// <summary>
/// 通行证客户端 XRPC 版
/// </summary>
[HttpClient(HttpClientConfigration.XRpc)]
internal class PassportClient2
{
private readonly HttpClient httpClient;
private readonly JsonSerializerOptions options;
private readonly ILogger<PassportClient> logger;
/// <summary>
/// 构造一个新的通行证客户端
/// </summary>
/// <param name="httpClient">http客户端</param>
/// <param name="options">json序列化选项</param>
/// <param name="logger">日志器</param>
public PassportClient2(HttpClient httpClient, JsonSerializerOptions options, ILogger<PassportClient> logger)
{
this.httpClient = httpClient;
this.options = options;
this.logger = logger;
}
/// <summary>
/// 异步获取 CookieToken
/// </summary>
/// <param name="user">用户</param>
/// <param name="token">取消令牌</param>
/// <returns>uid 与 cookie token</returns>
[ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.PROD)]
public async Task<UidCookieToken?> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token)
{
Response<UidCookieToken>? resp = await httpClient
.SetUser(user, CookieType.Stoken)
.UsingDynamicSecret2(SaltType.PROD, options, ApiEndpoints.AccountCookieAccountInfoBySToken)
.TryCatchGetFromJsonAsync<Response<UidCookieToken>>(logger, token)
.ConfigureAwait(false);
return resp?.Data;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Passport;
/// <summary>
/// uid 与 cookie token
/// </summary>
public class UidCookieToken
{
/// <summary>
/// Uid
/// </summary>
[JsonPropertyName("uid")]
public string Uid { get; set; } = default!;
/// <summary>
/// CookieToken
/// </summary>
[JsonPropertyName("cookie_token")]
public string CookieToken { get; set; } = default!;
}