You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
12 KiB
351 lines
12 KiB
1 month ago
|
using System.Collections.Generic;
|
||
|
using System.Net.Http;
|
||
|
using System.Text;
|
||
|
using Sog;
|
||
|
using LitJson;
|
||
|
using System.Text.Json;
|
||
|
|
||
|
namespace HttpProxy
|
||
|
{
|
||
|
public class HuaweiAuth
|
||
|
{
|
||
|
// HMSCore接入信息
|
||
|
|
||
|
// 解析access Token信息的地址
|
||
|
private static string GetAccessTokenInfoUrl = "https://oauth-api.cloud.huawei.com/rest.php";
|
||
|
|
||
|
// 解析ID Token信息的地址
|
||
|
private static string GetIDTokenInfoUrl = "https://oauth-login.cloud.huawei.com/oauth2/v3/tokeninfo";
|
||
|
|
||
|
|
||
|
private static string NSP_SVC = "huawei.oauth2.user.getTokenInfo";
|
||
|
|
||
|
// 游戏产品在SDK平台的应用ID
|
||
|
private static string ClientId = "105624843";
|
||
|
|
||
|
// 游戏产品在SDK平台的应用私钥
|
||
|
private static string ClientSecret = "1913208d8b4d11a0d9c1c3c096318ad84c8a41ef9105313ea5f2ad245ebc5d96";
|
||
|
|
||
|
// idtoken校验中返回的iss字段值, 需要验证是否匹配
|
||
|
private static string IDTOKEN_ISS = "https://accounts.huawei.com";
|
||
|
|
||
|
// AppGallery Connect接入信息
|
||
|
private static string AGC_ProductId = "737518067794508975";
|
||
|
|
||
|
private static string AGC_ClientId = "910058972399029696";
|
||
|
|
||
|
private static string AGC_ClientSecret = "F745EDA6D66B71030543B9B2D73E91951D5C3389930D7508648044ED195D441F";
|
||
|
|
||
|
private static string AGC_GetTokenUrl = "https://connect-api.cloud.huawei.com/api/oauth2/v1/token";
|
||
|
|
||
|
// 德国站点地址
|
||
|
private static string AGC_VerifyTokenInfoUrl =
|
||
|
"https://connect-api-dre.cloud.huawei.com/api/oauth2/third/v1/verify-token?productId=737518067794508975";
|
||
|
|
||
|
// 服务器向华为SDK服务器请求时用的AccessToken
|
||
|
private static string AGC_AccessToken;
|
||
|
private static long AGC_AccessTokenExpireTime;
|
||
|
|
||
|
|
||
|
private static long nextTickTimeMs;
|
||
|
|
||
|
|
||
|
public static void Init(string clientId, string clientSecret, string accessTokenUrl, string idTokenUrl)
|
||
|
{
|
||
|
if (! string.IsNullOrEmpty(clientId))
|
||
|
{
|
||
|
ClientId = clientId;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(clientSecret))
|
||
|
{
|
||
|
ClientSecret = clientSecret;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(accessTokenUrl))
|
||
|
{
|
||
|
GetAccessTokenInfoUrl = accessTokenUrl;
|
||
|
}
|
||
|
|
||
|
if (!string.IsNullOrEmpty(idTokenUrl))
|
||
|
{
|
||
|
GetIDTokenInfoUrl = idTokenUrl;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.Init clientId {0} clientSecret {1} accessTokenUrl {2} idTokenUrl {3}"
|
||
|
, ClientId, ClientSecret, GetAccessTokenInfoUrl, GetIDTokenInfoUrl);
|
||
|
}
|
||
|
|
||
|
public static void InitAGC(string clientId, string clientSecret, string getTokenUrl,
|
||
|
string verifyTokenUrl, string productId)
|
||
|
{
|
||
|
if (! string.IsNullOrEmpty(clientId))
|
||
|
{
|
||
|
AGC_ClientId = clientId;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(clientSecret))
|
||
|
{
|
||
|
AGC_ClientSecret = clientSecret;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(getTokenUrl))
|
||
|
{
|
||
|
AGC_GetTokenUrl = getTokenUrl;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(productId))
|
||
|
{
|
||
|
AGC_ProductId = productId;
|
||
|
}
|
||
|
|
||
|
if (! string.IsNullOrEmpty(verifyTokenUrl) && ! string.IsNullOrEmpty(productId))
|
||
|
{
|
||
|
AGC_VerifyTokenInfoUrl = verifyTokenUrl + "productId=" + productId;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.InitAGC clientId {0} clientSecret {1} getTokenUrl {2} verifyTokenUrl {3}"
|
||
|
, AGC_ClientId, AGC_ClientSecret, AGC_GetTokenUrl, AGC_VerifyTokenInfoUrl);
|
||
|
}
|
||
|
|
||
|
public static bool GetAccessTokenInfo(string openId, string accessToken)
|
||
|
{
|
||
|
var allParams = new Dictionary<string, string>();
|
||
|
allParams["nsp_svc"] = NSP_SVC;
|
||
|
allParams["open_id"] = "OPENID";
|
||
|
allParams["access_token"] = accessToken;
|
||
|
|
||
|
var content = new FormUrlEncodedContent(allParams);
|
||
|
string ret = HttpUtils.HttpPost(GetAccessTokenInfoUrl, content, out bool exception);
|
||
|
if (ret == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetAccessTokenInfo HttpPost failed");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.GetAccessTokenInfo ret {0}", ret);
|
||
|
|
||
|
JsonData jsonData = JsonMapper.ToObject(ret);
|
||
|
if (! jsonData.ContainsKey("open_id"))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetAccessTokenInfo no [open_id]");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
string resOpenId = jsonData["open_id"].ToString();
|
||
|
if (! resOpenId.Equals(openId))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetAccessTokenInfo openId {0} res {1} not same", openId, resOpenId);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static bool GetIDTokenInfo(string openId, string idToken)
|
||
|
{
|
||
|
var allParams = new Dictionary<string, string>();
|
||
|
allParams["id_token"] = idToken;
|
||
|
|
||
|
var content = new FormUrlEncodedContent(allParams);
|
||
|
string ret = HttpUtils.HttpPost(GetIDTokenInfoUrl, content, out bool exception);
|
||
|
if (ret == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetIDTokenInfo HttpPost failed");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.GetIDTokenInfo ret {0}", ret);
|
||
|
|
||
|
JsonData jsonData = JsonMapper.ToObject(ret);
|
||
|
if (!jsonData.ContainsKey("iss"))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetIDTokenInfo no [iss]");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!jsonData.ContainsKey("aud"))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetIDTokenInfo no [aud]");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!jsonData.ContainsKey("exp"))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetIDTokenInfo no [exp]");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
long exp = (long)jsonData["exp"];
|
||
|
if (HttpProxyServerUtils.GetTimeSecond() >= exp)
|
||
|
{
|
||
|
TraceLog.Trace("HuaweiAuth.GetIDTokenInfo token expire at {0}", exp);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
string iss = jsonData["iss"].ToString();
|
||
|
string aud = jsonData["aud"].ToString();
|
||
|
if (! iss.Equals(IDTOKEN_ISS) || ! aud.Equals(ClientId))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.GetIDTokenInfo invalid iss {0} aud {1}", iss, aud);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static void Update(long nowSec)
|
||
|
{
|
||
|
//配置文件没配置,不update,要不一堆异常 2022/12/21 zouwei
|
||
|
if(string.IsNullOrEmpty(HttpProxyServerUtils.GetServerConfig().huaweiAGC_ClientId))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (nowSec < nextTickTimeMs)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 10秒tick 1次
|
||
|
nextTickTimeMs = nowSec + 10;
|
||
|
|
||
|
// token过期前10分钟开始尝试刷新
|
||
|
if (nowSec + 600 >= AGC_AccessTokenExpireTime)
|
||
|
{
|
||
|
UpdateAGCAccessToken();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// 刷新AGC服务器请求时需要的AccessToken
|
||
|
public static int UpdateAGCAccessToken()
|
||
|
{
|
||
|
Dictionary<string, string> bodyMap = new Dictionary<string, string>();
|
||
|
bodyMap.Add("client_id", AGC_ClientId);
|
||
|
bodyMap.Add("client_secret", AGC_ClientSecret);
|
||
|
bodyMap.Add("grant_type", "client_credentials");
|
||
|
var bodyString = JsonSerializer.Serialize(bodyMap);
|
||
|
var httpContent = new StringContent(bodyString, Encoding.UTF8, "application/json");
|
||
|
|
||
|
string httpRet = HttpUtils.HttpPost(AGC_GetTokenUrl, httpContent, null, 10, out int statusCode);
|
||
|
TraceLog.Debug("HuaweiAuth.UpdateAGCAccessToken HttpPost res status code {0}", statusCode);
|
||
|
|
||
|
if (httpRet == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken HttpPost return null");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.UpdateAGCAccessToken ret {0}", httpRet);
|
||
|
|
||
|
JsonData jsonData = JsonMapper.ToObject(httpRet);
|
||
|
// 获取失败时会返回ret, 成功则不会
|
||
|
if (jsonData.ContainsKey("ret"))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken get access token failed");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JsonData accToken = jsonData["access_token"];
|
||
|
if (accToken == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken res no [access_token]");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JsonData validTime = jsonData["expires_in"];
|
||
|
if (validTime == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken res no [expires_in]");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (! long.TryParse(validTime.ToString(), out long validTimeSec))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken invalid [expires_in] {0}", validTime.ToString());
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
AGC_AccessToken = accToken.ToString();
|
||
|
AGC_AccessTokenExpireTime = HttpProxyServerUtils.GetTimeSecond() + validTimeSec;
|
||
|
|
||
|
// 打印错误日志不容易被冲掉
|
||
|
TraceLog.Error("HuaweiAuth.UpdateAGCAccessToken succ, token {0} expire {1}", AGC_AccessToken, AGC_AccessTokenExpireTime);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
// 校验用户上报的AccountToken
|
||
|
public static int VerifyAGCUserToken(string accountId, string userToken)
|
||
|
{
|
||
|
Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
|
||
|
httpHeaders.Add("client_id", AGC_ClientId);
|
||
|
httpHeaders.Add("accessToken", userToken);
|
||
|
httpHeaders.Add("Authorization", $"Bearer {AGC_AccessToken}");
|
||
|
|
||
|
string httpRet = HttpUtils.HttpGet(AGC_VerifyTokenInfoUrl, out bool ex, httpHeaders);
|
||
|
if (httpRet == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken token {0} HttpGet return null", userToken);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.VerifyAGCUserToken token {0} ret {1}", userToken, httpRet);
|
||
|
|
||
|
JsonData jsonData = JsonMapper.ToObject(httpRet);
|
||
|
JsonData ret = jsonData["ret"];
|
||
|
if (! int.TryParse(ret["code"].ToString(), out int retCode))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken invalid ret code {0}", ret["code"].ToString());
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (retCode != 0)
|
||
|
{
|
||
|
TraceLog.Trace("HuaweiAuth.VerifyAGCUserToken invalid ret code {0}", retCode);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JsonData uid = jsonData["uid"];
|
||
|
if (uid == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken res no [uid]");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
string resUid = uid.ToString();
|
||
|
if (! accountId.Equals(resUid))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken accountId {0} {1} not same", accountId, resUid);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
JsonData accToken = jsonData["accessToken"];
|
||
|
if (accToken == null)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken res no [accessToken]");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (! long.TryParse(accToken["validPeriod"].ToString(), out long validTime))
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken invalid token time {0}", accToken["validPeriod"].ToString());
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (validTime <= 0)
|
||
|
{
|
||
|
TraceLog.Error("HuaweiAuth.VerifyAGCUserToken invalid token time {0}", validTime);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
TraceLog.Trace("HuaweiAuth.VerifyAGCUserToken {0} validTime {1} succ", userToken, validTime);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|