|
@@ -0,0 +1,386 @@
|
|
|
+using HiTeachCC.Library.Common;
|
|
|
+using HiTeachCC.Model.Core.Dtos;
|
|
|
+using HiTeachCC.Model.Core.Models;
|
|
|
+using HiTeachCC.Service.Core.Interface;
|
|
|
+using IdentityModel;
|
|
|
+using Microsoft.Extensions.Configuration;
|
|
|
+using Microsoft.Extensions.Options;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Security.Claims;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using TEAMModelOS.SDK.Context.Configuration;
|
|
|
+using TEAMModelOS.SDK.Context.Constant.Common;
|
|
|
+using TEAMModelOS.SDK.Context.Exception;
|
|
|
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
|
|
|
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
|
|
|
+using TEAMModelOS.SDK.Extension.HttpClient.Implements;
|
|
|
+using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
|
|
|
+using TEAMModelOS.SDK.Extension.JwtAuth.Models;
|
|
|
+using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
|
|
|
+using TEAMModelOS.SDK.Helper.Common.JsonHelper;
|
|
|
+using TEAMModelOS.SDK.Helper.Network.HttpHelper;
|
|
|
+using TEAMModelOS.SDK.Helper.Security.BCryptHelper;
|
|
|
+
|
|
|
+namespace HiTeachCC.Service.Core.Implement
|
|
|
+{
|
|
|
+ public class LoginInfoService : BaseService, ILoginInfoService
|
|
|
+ {
|
|
|
+ private readonly HttpClientUserInfo _httpClientService;
|
|
|
+
|
|
|
+ public LoginInfoService(HttpClientUserInfo httpClientUserInfo)
|
|
|
+ {
|
|
|
+ _httpClientService = httpClientUserInfo;
|
|
|
+ }
|
|
|
+ public async Task<object> VerifyWeChat(Dictionary<string, object> dict) {
|
|
|
+ if (dict.TryGetValue("code", out object code)) {
|
|
|
+ WeChatToken oauth2Token = await GetWeChatAccessToken(code!=null?code.ToString():"");
|
|
|
+ oauth2Token.RowKey = oauth2Token.access_token;
|
|
|
+ oauth2Token.PartitionKey = "WeChatOauth2Token";
|
|
|
+ oauth2Token = await SaveOrUpdate<WeChatToken>(oauth2Token);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取微信AccessToken
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Code"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private async Task<WeChatToken> GetWeChatAccessTokenClient()
|
|
|
+ {
|
|
|
+
|
|
|
+ string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlClient"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=client_credential";
|
|
|
+ requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
|
|
|
+ string info = await HttpHelper.HttpGetAsync(requestUrl);
|
|
|
+ return MessagePackHelper.JsonToObject<WeChatToken>(info);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取微信AccessToken
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Code"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private async Task<WeChatToken> GetWeChatAccessToken(string Code ) {
|
|
|
+ if (string.IsNullOrEmpty(Code)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ string requestUrl = BaseConfigModel.Configuration["HaBookAuth:WeChatAccessTokenUrlCode"] + "appid={{APPID}}&secret={{SECRET}}&code={{CODE}}&grant_type=authorization_code";
|
|
|
+ requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppID"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:WeChatAppSecret"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{CODE}}", Code);
|
|
|
+ string info= await HttpHelper.HttpGetAsync(requestUrl);
|
|
|
+ return MessagePackHelper.JsonToObject<WeChatToken>(info);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取微信登录跳转链接
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="time">13位时间戳</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public Dictionary<string, object> GetWechatConfig(string Time)
|
|
|
+ {
|
|
|
+ Dictionary<string, object> config = new Dictionary<string, object>();
|
|
|
+ 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");
|
|
|
+ return config;
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<MiniAPPLoginInfo> VerifyMiniAPP(Dictionary<string, object> dict)
|
|
|
+ {
|
|
|
+ MiniAPPLoginInfo loginInfo = null ;
|
|
|
+ if (dict.TryGetValue("js_code", out object js_code))
|
|
|
+ {
|
|
|
+ if (string.IsNullOrEmpty(js_code != null ? js_code.ToString() : ""))
|
|
|
+ {
|
|
|
+ throw new Exception( "Validation failure , js_code is null!");
|
|
|
+ }
|
|
|
+ string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAuthUrl"];
|
|
|
+ requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{JSCODE}}", js_code.ToString());
|
|
|
+ string info = await HttpHelper.HttpGetAsync(requestUrl);
|
|
|
+ loginInfo = MessagePackHelper.JsonToObject<MiniAPPLoginInfo>(info);
|
|
|
+ if (loginInfo != null)
|
|
|
+ {
|
|
|
+ if (loginInfo.errcode != 0)
|
|
|
+ {
|
|
|
+ throw new Exception( loginInfo.errmsg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Exception( "Validation failure , loginInfo is null !");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Exception( "js_code is null !");
|
|
|
+ }
|
|
|
+ return loginInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取微信AccessToken
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Code"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public async Task<MiniAPPToken> GetMiniAPPAccessToken()
|
|
|
+ {
|
|
|
+ string requestUrl = BaseConfigModel.Configuration["HaBookAuth:MiniAPPAccessTokenUrl"];
|
|
|
+ requestUrl = requestUrl.Replace("{{APPID}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPID"]);
|
|
|
+ requestUrl = requestUrl.Replace("{{SECRET}}", BaseConfigModel.Configuration["HaBookAuth:MiniAPPSECRET"]);
|
|
|
+ string info = await HttpHelper.HttpGetAsync(requestUrl);
|
|
|
+ MiniAPPToken miniAPPToken= MessagePackHelper.JsonToObject<MiniAPPToken>(info);
|
|
|
+ if (miniAPPToken != null)
|
|
|
+ {
|
|
|
+ if (miniAPPToken.errcode != 0)
|
|
|
+ {
|
|
|
+ throw new Exception( miniAPPToken.errmsg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Exception( "Validation failure,miniAPPToken is null!");
|
|
|
+ }
|
|
|
+ return miniAPPToken;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 获取用户登录信息
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="unionid"></param>
|
|
|
+ /// <param name="access_token"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public async Task<WeChatUser> GetWeChatUserInfo(string session_key ,Dictionary<string ,object> dict) {
|
|
|
+ string enData = "";
|
|
|
+ if (dict.TryGetValue("encryptedData", out object encryptedData) && dict.TryGetValue("iv", out object iv)) {
|
|
|
+ if (encryptedData != null && iv != null) {
|
|
|
+ /**
|
|
|
+ *{"openId":"oLaYK45lBS8HWSAXJisDdIlEWj3A",
|
|
|
+ * "nickName":"菁華浮梦、℡",
|
|
|
+ * "gender":1,
|
|
|
+ * "language":"zh_CN",
|
|
|
+ * "city":"Chengdu",
|
|
|
+ * "province":"Sichuan",
|
|
|
+ * "country":"China",
|
|
|
+ * "avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/DYAIOgq83er98z4MsFd1xKML71TwQuR1Bxnt7ib3SGrNsKiaBCLYbLeS7KAT8h0ia8byiaVzurvEpVmmQpSzBQs5Nw/132",
|
|
|
+ * "unionId":"oqADO5qdTR6PItxhmDEPCsWU9PqI",
|
|
|
+ * "watermark":{"timestamp":1562224447,"appid":"wxf4905703824211aa"}}
|
|
|
+ **/
|
|
|
+ enData = WeChatCryptHelper.AESDecrypt(encryptedData.ToString(),session_key,iv.ToString());
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //string requestUrl = BaseConfigModel.Configuration["HaBookAuth:UnionidUserinfo"];
|
|
|
+ //requestUrl = requestUrl.Replace("{{openid}}", unionid);
|
|
|
+ //WeChatToken weChatToken = await GetWeChatAccessTokenClient();
|
|
|
+ //requestUrl = requestUrl.Replace("{{access_token}}", weChatToken.access_token);
|
|
|
+ //string info = await HttpHelper.HttpGetAsync(requestUrl);
|
|
|
+ MiniAPPUserInfo miniAPPUser = MessagePackHelper.JsonToObject<MiniAPPUserInfo>(enData);
|
|
|
+ if (miniAPPUser != null)
|
|
|
+ {
|
|
|
+ WeChatUser weChatUser = new WeChatUser();
|
|
|
+ weChatUser.RowKey = miniAPPUser.unionId;
|
|
|
+ weChatUser.PartitionKey = miniAPPUser.country;
|
|
|
+ weChatUser.nickName = miniAPPUser.nickName;
|
|
|
+ weChatUser.gender = miniAPPUser.gender;
|
|
|
+ weChatUser.avatarUrl = miniAPPUser.avatarUrl;
|
|
|
+ weChatUser.country = miniAPPUser.country;
|
|
|
+ weChatUser.city = miniAPPUser.city;
|
|
|
+ weChatUser.province = miniAPPUser.province;
|
|
|
+ weChatUser.openId = miniAPPUser.openId;
|
|
|
+ weChatUser.unionId = miniAPPUser.unionId;
|
|
|
+ weChatUser.appid = miniAPPUser.watermark.appid;
|
|
|
+ await SaveOrUpdate<WeChatUser>(weChatUser);
|
|
|
+ return weChatUser;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Exception( "Validation failure,miniAPPToken is null!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public async Task<JwtResponse> MiniAPPLogin(Dictionary<string, object> dict) {
|
|
|
+ MiniAPPLoginInfo loginInfo= await VerifyMiniAPP(dict);
|
|
|
+ WeChatUser weChatUser = await GetWeChatUserInfo(loginInfo.session_key , dict);
|
|
|
+ JwtResponse jwt= CreateJwtToken(weChatUser);
|
|
|
+ LoginInfo login = new LoginInfo();
|
|
|
+ login.RowKey = Guid.NewGuid().ToString();
|
|
|
+ login.PartitionKey = weChatUser.PartitionKey;
|
|
|
+ login.TeamModelId = weChatUser.unionId;
|
|
|
+ login.Token = jwt.Access_token;
|
|
|
+ login.Scope = jwt.Scope;
|
|
|
+ return jwt;
|
|
|
+ }
|
|
|
+ public JwtResponse CreateJwtToken(WeChatUser user) {
|
|
|
+ ClaimModel model = new ClaimModel
|
|
|
+ {
|
|
|
+ Scope = "MiniAPP"
|
|
|
+ };
|
|
|
+ if (user!=null )
|
|
|
+ {
|
|
|
+ model.Claims.Add(new Claim(JwtClaimTypes.Name, user.nickName));
|
|
|
+ model.Claims.Add(new Claim(JwtClaimTypes.Id, user.unionId));
|
|
|
+ model.Claims.AddRange("Student".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
|
|
|
+ model.Roles.Add("Student");
|
|
|
+ JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
|
|
|
+ return jwtResponse;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new Exception( "Validation failure,user is null !");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public JwtResponse CreateJwtToken(LoginInfo login) {
|
|
|
+ ClaimModel model = new ClaimModel
|
|
|
+ {
|
|
|
+ Scope = "WebAPP"
|
|
|
+ };
|
|
|
+ if (login != null)
|
|
|
+ {
|
|
|
+ model.Claims.Add(new Claim(JwtClaimTypes.Name, login.Name));
|
|
|
+ model.Claims.Add(new Claim(JwtClaimTypes.Id, login.TeamModelId));
|
|
|
+ model.Claims.AddRange("Student".Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
|
|
|
+ model.Roles.Add("Teacher");
|
|
|
+ JwtResponse jwtResponse = JwtHelper.IssueJWT(model, BaseConfigModel.Configuration.GetSection("JwtSetting").Get<JwtSetting>());
|
|
|
+ return jwtResponse;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new Exception("Validation failure,user is null !");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<JwtResponse> TeamModelLogin(TicketInfo ticketInfo) {
|
|
|
+ if (string.IsNullOrEmpty(ticketInfo.Token))
|
|
|
+ {
|
|
|
+ if (string.IsNullOrEmpty(ticketInfo.Ticket))
|
|
|
+ {
|
|
|
+ throw new BizException(401, "Unauthorized");
|
|
|
+ }
|
|
|
+ string code = BCryptHelper.Ecrypt(ticketInfo.Ticket + ticketInfo.TeamModelId);
|
|
|
+ bool f = BCryptHelper.Verify(ticketInfo.Ticket + ticketInfo.TeamModelId, ticketInfo.Sign);
|
|
|
+ LoginInfo login = FindOneByKey<LoginInfo>("Ticket", ticketInfo.Ticket).Result;
|
|
|
+ if (login != null && !string.IsNullOrEmpty(login.Token))
|
|
|
+ {
|
|
|
+ JwtResponse token = CreateJwtToken(login);
|
|
|
+ login.Token = token.Access_token;
|
|
|
+ await Update<LoginInfo>(login);
|
|
|
+ return token;
|
|
|
+ }
|
|
|
+
|
|
|
+ ///不验证TmdID
|
|
|
+ #region
|
|
|
+ /*
|
|
|
+ LoginInfo loginInfo = new LoginInfo
|
|
|
+ {
|
|
|
+ PartitionKey = "15283771540",
|
|
|
+ Phone = "15283771540",
|
|
|
+ RowKey = Guid.NewGuid().ToString(),
|
|
|
+ TeamModelId = ticketInfo.TeamModelId,
|
|
|
+ Name = ticketInfo.Name,
|
|
|
+ Ticket = ticketInfo.Ticket,
|
|
|
+ CountryCode = "86"
|
|
|
+ };
|
|
|
+ TeamModelUser user = await FindOneByKey<TeamModelUser>("TeamModelId", ticketInfo.TeamModelId);
|
|
|
+ if (user == null || string.IsNullOrEmpty(user.RowKey))
|
|
|
+ {
|
|
|
+ user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode, registerTime = DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
|
|
|
+ }
|
|
|
+ user.cellphone = "15283771540";
|
|
|
+ user.nickname = ticketInfo.Name;
|
|
|
+ if (string.IsNullOrEmpty(user.fullName))
|
|
|
+ {
|
|
|
+ user.fullName = ticketInfo.Name;
|
|
|
+ }
|
|
|
+ user.teamModelId = ticketInfo.TeamModelId;
|
|
|
+ user.phoneCode = "86";
|
|
|
+ JwtResponse jwtToken = CreateJwtToken(loginInfo);
|
|
|
+ loginInfo.Token = jwtToken.Access_token;
|
|
|
+ loginInfo.Scope = jwtToken.Scope;
|
|
|
+ await Save<LoginInfo>(loginInfo);
|
|
|
+ await SaveOrUpdate<TeamModelUser>(user);
|
|
|
+ return jwtToken;
|
|
|
+ */
|
|
|
+ #endregion
|
|
|
+ JosnRPCRequest<Dictionary<string, object>> request = new JosnRPCRequest<Dictionary<string, object>>
|
|
|
+ {
|
|
|
+ method = "UserInfo"
|
|
|
+ };
|
|
|
+
|
|
|
+ Dictionary<string, object> ticket = new Dictionary<string, object>
|
|
|
+ {
|
|
|
+ { "ticket", ticketInfo.Ticket }
|
|
|
+ };
|
|
|
+ request.@params = ticket;
|
|
|
+ string data = MessagePackHelper.ObjectToJson(request);
|
|
|
+ string jsonStr = _httpClientService.HttpPost(BaseConfigModel.Configuration["HaBookAuth:AccountUrl"], data, Constants.CONTENT_TYPE_JSON, Encoding.UTF8);
|
|
|
+ if (!string.IsNullOrEmpty(jsonStr))
|
|
|
+ {
|
|
|
+ JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
|
|
|
+ if (response.error == null && response != null)
|
|
|
+ {
|
|
|
+ LoginInfo loginInfo = new LoginInfo
|
|
|
+ {
|
|
|
+ PartitionKey = response.result.cellphone,
|
|
|
+ Phone = response.result.cellphone,
|
|
|
+ RowKey = Guid.NewGuid().ToString(),
|
|
|
+ TeamModelId = response.result.id,
|
|
|
+ Name = response.result.name,
|
|
|
+ Ticket = ticketInfo.Ticket,
|
|
|
+ CountryCode = response.result.countryCode
|
|
|
+ };
|
|
|
+ TeamModelUser user= await FindOneByKey<TeamModelUser>("TeamModelId", response.result.id);
|
|
|
+ if (user == null || string.IsNullOrEmpty(user.RowKey))
|
|
|
+ {
|
|
|
+ user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode ,registerTime=DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
|
|
|
+ }
|
|
|
+ user.cellphone = response.result.cellphone;
|
|
|
+ user.nickName = response.result.name;
|
|
|
+ if (string.IsNullOrEmpty(user.fullName)) {
|
|
|
+ user.fullName = response.result.name;
|
|
|
+ }
|
|
|
+ user.teamModelId = response.result.id;
|
|
|
+ user.phoneCode = response.result.countryCode;
|
|
|
+ JwtResponse jwtToken = CreateJwtToken(loginInfo);
|
|
|
+ loginInfo.Token = jwtToken.Access_token;
|
|
|
+ loginInfo.Scope = jwtToken.Scope;
|
|
|
+ await Save<LoginInfo>(loginInfo);
|
|
|
+ await SaveOrUpdate<TeamModelUser>(user);
|
|
|
+ return jwtToken;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new BizException(401, "Unauthorized");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new BizException(401, "Unauthorized");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ClaimModel claimModel = JwtHelper.SerializeJWT(ticketInfo.Token);
|
|
|
+ var dateTime = DateTimeHelper.ConvertToTimeStamp10(DateTime.Now);
|
|
|
+ var expExt = claimModel.Claim.TryGetValue("exp", out var exp);
|
|
|
+ if (expExt == false || dateTime > long.Parse(exp.ToString()))
|
|
|
+ {
|
|
|
+ throw new BizException(401, "Unauthorized");
|
|
|
+ }
|
|
|
+ Dictionary<string, object> msp = new Dictionary<string, object>
|
|
|
+ {
|
|
|
+ { "Token", ticketInfo.Token }
|
|
|
+ };
|
|
|
+ LoginInfo loginInfo = FindOneByDict<LoginInfo>(msp).Result;
|
|
|
+ if (loginInfo != null && !string.IsNullOrEmpty(loginInfo.Token))
|
|
|
+ {
|
|
|
+ return new JwtResponse { Access_token = loginInfo.Token, Scope = loginInfo.Scope };
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new BizException(401, "Unauthorized");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|