LoginInfoService.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. using HiTeachCC.Library.Common;
  2. using HiTeachCC.Model.Core.Dtos;
  3. using HiTeachCC.Model.Core.Models;
  4. using HiTeachCC.Service.Core.Interface;
  5. using IdentityModel;
  6. using Microsoft.Extensions.Configuration;
  7. using Microsoft.Extensions.Options;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Security.Claims;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using TEAMModelOS.SDK.Context.Configuration;
  15. using TEAMModelOS.SDK.Context.Constant.Common;
  16. using TEAMModelOS.SDK.Context.Exception;
  17. using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
  18. using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
  19. using TEAMModelOS.SDK.Extension.HttpClient.Implements;
  20. using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
  21. using TEAMModelOS.SDK.Extension.JwtAuth.Models;
  22. using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
  23. using TEAMModelOS.SDK.Helper.Common.JsonHelper;
  24. using TEAMModelOS.SDK.Helper.Network.HttpHelper;
  25. using TEAMModelOS.SDK.Helper.Security.BCryptHelper;
  26. namespace HiTeachCC.Service.Core.Implement
  27. {
  28. public class LoginInfoService : BaseService, ILoginInfoService
  29. {
  30. private readonly HttpClientUserInfo _httpClientService;
  31. public LoginInfoService(HttpClientUserInfo httpClientUserInfo)
  32. {
  33. _httpClientService = httpClientUserInfo;
  34. }
  35. public async Task<object> VerifyWeChat(Dictionary<string, object> dict) {
  36. if (dict.TryGetValue("code", out object code)) {
  37. WeChatToken oauth2Token = await GetWeChatAccessToken(code!=null?code.ToString():"");
  38. oauth2Token.RowKey = oauth2Token.access_token;
  39. oauth2Token.PartitionKey = "WeChatOauth2Token";
  40. oauth2Token = await SaveOrUpdate<WeChatToken>(oauth2Token);
  41. }
  42. return null;
  43. }
  44. /// <summary>
  45. /// 获取微信AccessToken
  46. /// </summary>
  47. /// <param name="Code"></param>
  48. /// <returns></returns>
  49. private async Task<WeChatToken> GetWeChatAccessTokenClient()
  50. {
  51. string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlClient"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=client_credential";
  52. requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
  53. requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
  54. string info = await HttpHelper.HttpGetAsync(requestUrl);
  55. return MessagePackHelper.JsonToObject<WeChatToken>(info);
  56. }
  57. /// <summary>
  58. /// 获取微信AccessToken
  59. /// </summary>
  60. /// <param name="Code"></param>
  61. /// <returns></returns>
  62. private async Task<WeChatToken> GetWeChatAccessToken(string Code ) {
  63. if (string.IsNullOrEmpty(Code)) {
  64. return null;
  65. }
  66. string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlCode"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=authorization_code";
  67. requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
  68. requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
  69. requestUrl = requestUrl.Replace("{{CODE}}", Code);
  70. string info= await HttpHelper.HttpGetAsync(requestUrl);
  71. return MessagePackHelper.JsonToObject<WeChatToken>(info);
  72. }
  73. /// <summary>
  74. /// 获取微信登录跳转链接
  75. /// </summary>
  76. /// <param name="time">13位时间戳</param>
  77. /// <returns></returns>
  78. public Dictionary<string, object> GetWechatConfig(string Time)
  79. {
  80. Dictionary<string, object> config = new Dictionary<string, object>();
  81. config.Add("WeChatAuthorizeUrlCode", BaseConfigModel.Configuration["HaBookAuth:WeChatAuthorizeUrlCode"] + "?appid="+ BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"] + "&redirect_uri={{redirect_uri}}&response_type=code&scope=snsapi_userinfo&state="+ Time + "#wechat_redirect");
  82. return config;
  83. }
  84. public async Task<MiniAPPLoginInfo> VerifyMiniAPP(Dictionary<string, object> dict)
  85. {
  86. MiniAPPLoginInfo loginInfo = null ;
  87. if (dict.TryGetValue("js_code", out object js_code))
  88. {
  89. if (string.IsNullOrEmpty(js_code != null ? js_code.ToString() : ""))
  90. {
  91. throw new Exception( "Validation failure , js_code is null!");
  92. }
  93. string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAuthUrl"];
  94. requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
  95. requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
  96. requestUrl = requestUrl.Replace("{{JSCODE}}", js_code.ToString());
  97. string info = await HttpHelper.HttpGetAsync(requestUrl);
  98. loginInfo = MessagePackHelper.JsonToObject<MiniAPPLoginInfo>(info);
  99. if (loginInfo != null)
  100. {
  101. if (loginInfo.errcode != 0)
  102. {
  103. throw new Exception( loginInfo.errmsg);
  104. }
  105. }
  106. else {
  107. throw new Exception( "Validation failure , loginInfo is null !");
  108. }
  109. }
  110. else {
  111. throw new Exception( "js_code is null !");
  112. }
  113. return loginInfo;
  114. }
  115. /// <summary>
  116. /// 获取微信AccessToken
  117. /// </summary>
  118. /// <param name="Code"></param>
  119. /// <returns></returns>
  120. public async Task<MiniAPPToken> GetMiniAPPAccessToken()
  121. {
  122. string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAccessTokenUrl"];
  123. requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
  124. requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
  125. string info = await HttpHelper.HttpGetAsync(requestUrl);
  126. MiniAPPToken miniAPPToken= MessagePackHelper.JsonToObject<MiniAPPToken>(info);
  127. if (miniAPPToken != null)
  128. {
  129. if (miniAPPToken.errcode != 0)
  130. {
  131. throw new Exception( miniAPPToken.errmsg);
  132. }
  133. }
  134. else {
  135. throw new Exception( "Validation failure,miniAPPToken is null!");
  136. }
  137. return miniAPPToken;
  138. }
  139. /// <summary>
  140. /// 获取用户登录信息
  141. /// </summary>
  142. /// <param name="unionid"></param>
  143. /// <param name="access_token"></param>
  144. /// <returns></returns>
  145. public async Task<WeChatUser> GetWeChatUserInfo(string session_key ,Dictionary<string ,object> dict) {
  146. string enData = "";
  147. if (dict.TryGetValue("encryptedData", out object encryptedData) && dict.TryGetValue("iv", out object iv)) {
  148. if (encryptedData != null && iv != null) {
  149. /**
  150. *{"openId":"oLaYK45lBS8HWSAXJisDdIlEWj3A",
  151. * "nickName":"菁華浮梦、℡",
  152. * "gender":1,
  153. * "language":"zh_CN",
  154. * "city":"Chengdu",
  155. * "province":"Sichuan",
  156. * "country":"China",
  157. * "avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/DYAIOgq83er98z4MsFd1xKML71TwQuR1Bxnt7ib3SGrNsKiaBCLYbLeS7KAT8h0ia8byiaVzurvEpVmmQpSzBQs5Nw/132",
  158. * "unionId":"oqADO5qdTR6PItxhmDEPCsWU9PqI",
  159. * "watermark":{"timestamp":1562224447,"appid":"wxf4905703824211aa"}}
  160. **/
  161. enData = WeChatCryptHelper.AESDecrypt(encryptedData.ToString(),session_key,iv.ToString());
  162. }
  163. }
  164. //string requestUrl = BaseConfigModel.Configuration["HaBookAuth:UnionidUserinfo"];
  165. //requestUrl = requestUrl.Replace("{{openid}}", unionid);
  166. //WeChatToken weChatToken = await GetWeChatAccessTokenClient();
  167. //requestUrl = requestUrl.Replace("{{access_token}}", weChatToken.access_token);
  168. //string info = await HttpHelper.HttpGetAsync(requestUrl);
  169. MiniAPPUserInfo miniAPPUser = MessagePackHelper.JsonToObject<MiniAPPUserInfo>(enData);
  170. if (miniAPPUser != null)
  171. {
  172. WeChatUser weChatUser = new WeChatUser();
  173. weChatUser.RowKey = miniAPPUser.unionId;
  174. weChatUser.PartitionKey = miniAPPUser.country;
  175. weChatUser.nickName = miniAPPUser.nickName;
  176. weChatUser.gender = miniAPPUser.gender;
  177. weChatUser.avatarUrl = miniAPPUser.avatarUrl;
  178. weChatUser.country = miniAPPUser.country;
  179. weChatUser.city = miniAPPUser.city;
  180. weChatUser.province = miniAPPUser.province;
  181. weChatUser.openId = miniAPPUser.openId;
  182. weChatUser.unionId = miniAPPUser.unionId;
  183. weChatUser.appid = miniAPPUser.watermark.appid;
  184. await SaveOrUpdate<WeChatUser>(weChatUser);
  185. return weChatUser;
  186. }
  187. else {
  188. throw new Exception( "Validation failure,miniAPPToken is null!");
  189. }
  190. }
  191. public async Task<JwtResponse> MiniAPPLogin(Dictionary<string, object> dict) {
  192. MiniAPPLoginInfo loginInfo= await VerifyMiniAPP(dict);
  193. WeChatUser weChatUser = await GetWeChatUserInfo(loginInfo.session_key , dict);
  194. JwtResponse jwt= CreateJwtToken(weChatUser);
  195. LoginInfo login = new LoginInfo();
  196. login.RowKey = Guid.NewGuid().ToString();
  197. login.PartitionKey = weChatUser.PartitionKey;
  198. login.TeamModelId = weChatUser.unionId;
  199. login.Token = jwt.Access_token;
  200. login.Scope = jwt.Scope;
  201. return jwt;
  202. }
  203. public JwtResponse CreateJwtToken(WeChatUser user) {
  204. ClaimModel model = new ClaimModel
  205. {
  206. Scope = "MiniAPP"
  207. };
  208. if (user!=null )
  209. {
  210. model.Claims.Add(new Claim(JwtClaimTypes.Name, user.nickName));
  211. model.Claims.Add(new Claim(JwtClaimTypes.Id, user.unionId));
  212. model.Claims.AddRange("Student".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
  213. model.Roles.Add("Student");
  214. JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
  215. return jwtResponse;
  216. }
  217. else {
  218. throw new Exception( "Validation failure,user is null !");
  219. }
  220. }
  221. public JwtResponse CreateJwtToken(LoginInfo login) {
  222. ClaimModel model = new ClaimModel
  223. {
  224. Scope = "WebAPP"
  225. };
  226. if (login != null)
  227. {
  228. model.Claims.Add(new Claim(JwtClaimTypes.Name, login.Name));
  229. model.Claims.Add(new Claim(JwtClaimTypes.Id, login.TeamModelId));
  230. model.Claims.AddRange("Student".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
  231. model.Roles.Add("Teacher");
  232. JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
  233. return jwtResponse;
  234. }
  235. else
  236. {
  237. throw new Exception("Validation failure,user is null !");
  238. }
  239. }
  240. public async Task<JwtResponse> TeamModelLogin(TicketInfo ticketInfo) {
  241. if (string.IsNullOrEmpty(ticketInfo.Token))
  242. {
  243. if (string.IsNullOrEmpty(ticketInfo.Ticket))
  244. {
  245. throw new BizException(401, "Unauthorized");
  246. }
  247. string code = BCryptHelper.Ecrypt(ticketInfo.Ticket + ticketInfo.TeamModelId);
  248. bool f = BCryptHelper.Verify(ticketInfo.Ticket + ticketInfo.TeamModelId, ticketInfo.Sign);
  249. LoginInfo login = FindOneByKey<LoginInfo>("Ticket", ticketInfo.Ticket).Result;
  250. if (login != null && !string.IsNullOrEmpty(login.Token))
  251. {
  252. JwtResponse token = CreateJwtToken(login);
  253. login.Token = token.Access_token;
  254. await Update<LoginInfo>(login);
  255. return token;
  256. }
  257. ///不验证TmdID
  258. #region
  259. /*
  260. LoginInfo loginInfo = new LoginInfo
  261. {
  262. PartitionKey = "15283771540",
  263. Phone = "15283771540",
  264. RowKey = Guid.NewGuid().ToString(),
  265. TeamModelId = ticketInfo.TeamModelId,
  266. Name = ticketInfo.Name,
  267. Ticket = ticketInfo.Ticket,
  268. CountryCode = "86"
  269. };
  270. TeamModelUser user = await FindOneByKey<TeamModelUser>("TeamModelId", ticketInfo.TeamModelId);
  271. if (user == null || string.IsNullOrEmpty(user.RowKey))
  272. {
  273. user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode, registerTime = DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
  274. }
  275. user.cellphone = "15283771540";
  276. user.nickname = ticketInfo.Name;
  277. if (string.IsNullOrEmpty(user.fullName))
  278. {
  279. user.fullName = ticketInfo.Name;
  280. }
  281. user.teamModelId = ticketInfo.TeamModelId;
  282. user.phoneCode = "86";
  283. JwtResponse jwtToken = CreateJwtToken(loginInfo);
  284. loginInfo.Token = jwtToken.Access_token;
  285. loginInfo.Scope = jwtToken.Scope;
  286. await Save<LoginInfo>(loginInfo);
  287. await SaveOrUpdate<TeamModelUser>(user);
  288. return jwtToken;
  289. */
  290. #endregion
  291. JosnRPCRequest<Dictionary<string, object>> request = new JosnRPCRequest<Dictionary<string, object>>
  292. {
  293. method = "UserInfo"
  294. };
  295. Dictionary<string, object> ticket = new Dictionary<string, object>
  296. {
  297. { "ticket", ticketInfo.Ticket }
  298. };
  299. request.@params = ticket;
  300. string data = MessagePackHelper.ObjectToJson(request);
  301. string jsonStr = _httpClientService.HttpPost(BaseConfigModel.Configuration["HaBookAuth:AccountUrl"], data, Constants.CONTENT_TYPE_JSON, Encoding.UTF8);
  302. if (!string.IsNullOrEmpty(jsonStr))
  303. {
  304. JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
  305. if (response.error == null && response != null)
  306. {
  307. LoginInfo loginInfo = new LoginInfo
  308. {
  309. PartitionKey = response.result.cellphone,
  310. Phone = response.result.cellphone,
  311. RowKey = Guid.NewGuid().ToString(),
  312. TeamModelId = response.result.id,
  313. Name = response.result.name,
  314. Ticket = ticketInfo.Ticket,
  315. CountryCode = response.result.countryCode
  316. };
  317. TeamModelUser user= await FindOneByKey<TeamModelUser>("TeamModelId", response.result.id);
  318. if (user == null || string.IsNullOrEmpty(user.RowKey))
  319. {
  320. user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode ,registerTime=DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
  321. }
  322. user.cellphone = response.result.cellphone;
  323. user.nickName = response.result.name;
  324. if (string.IsNullOrEmpty(user.fullName)) {
  325. user.fullName = response.result.name;
  326. }
  327. user.teamModelId = response.result.id;
  328. user.phoneCode = response.result.countryCode;
  329. JwtResponse jwtToken = CreateJwtToken(loginInfo);
  330. loginInfo.Token = jwtToken.Access_token;
  331. loginInfo.Scope = jwtToken.Scope;
  332. await Save<LoginInfo>(loginInfo);
  333. await SaveOrUpdate<TeamModelUser>(user);
  334. return jwtToken;
  335. }
  336. else
  337. {
  338. throw new BizException(401, "Unauthorized");
  339. }
  340. }
  341. else
  342. {
  343. throw new BizException(401, "Unauthorized");
  344. }
  345. }
  346. else
  347. {
  348. ClaimModel claimModel = JwtHelper.SerializeJWT(ticketInfo.Token);
  349. var dateTime = DateTimeHelper.ConvertToTimeStamp10(DateTime.Now);
  350. var expExt = claimModel.Claim.TryGetValue("exp", out var exp);
  351. if (expExt == false || dateTime > long.Parse(exp.ToString()))
  352. {
  353. throw new BizException(401, "Unauthorized");
  354. }
  355. Dictionary<string, object> msp = new Dictionary<string, object>
  356. {
  357. { "Token", ticketInfo.Token }
  358. };
  359. LoginInfo loginInfo = FindOneByDict<LoginInfo>(msp).Result;
  360. if (loginInfo != null && !string.IsNullOrEmpty(loginInfo.Token))
  361. {
  362. return new JwtResponse { Access_token = loginInfo.Token, Scope = loginInfo.Scope };
  363. }
  364. else
  365. {
  366. throw new BizException(401, "Unauthorized");
  367. }
  368. }
  369. }
  370. }
  371. }