LoginInfoService.cs 19 KB

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