public async Task <IHttpActionResult> GuestLogin([FromBody] AccountLoginInfo info) { Logger.Info("Account.GuestLogin"); var r = new Random(); string accountNamePostfix = r.Next(0, 1000000).ToString("D6"); string accountName = $"uc_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{accountNamePostfix}"; string token = EncryptHashManager.GenerateToken(); string password = Guid.NewGuid().ToString(); var account = new AccountEntity { AccountName = accountName, IsGuest = true, Password = EncryptHashManager.ComputeHash(password), Token = EncryptHashManager.GenerateToken(), CreatedDateTime = DateTime.UtcNow }; await this.DatabaseContext.Bucket.InsertSlimAsync(account); var response = new AccountGuestLoginResponse { AccountId = account.Id, AccountName = accountName, Token = token, Password = password }; return(CreateSuccessResult(response)); }
public async Task <IHttpActionResult> Convert([FromBody] AccountConvertInfo info) { Logger.Info($"Account.Convert AccountName={info.AccountName}"); var account = await GetAndVerifyAccount(info.AccountId); if (!EncryptHashManager.VerifyHash(info.OldPassword, account.Password)) { await this.RecordLogin(account, UCenterErrorCode.AccountLoginFailedPasswordNotMatch, "The account name and password do not match"); throw new UCenterException(UCenterErrorCode.AccountLoginFailedPasswordNotMatch); } account.AccountName = info.AccountName; account.IsGuest = false; account.Name = info.Name; account.IdentityNum = info.IdentityNum; account.Password = EncryptHashManager.ComputeHash(info.Password); account.SuperPassword = EncryptHashManager.ComputeHash(info.SuperPassword); account.PhoneNum = info.PhoneNum; account.Email = info.Email; account.Sex = info.Sex; await this.DatabaseContext.Bucket.UpsertSlimAsync(account); await this.RecordLogin(account, UCenterErrorCode.Success, "Account converted successfully."); return(CreateSuccessResult(ToResponse <AccountRegisterResponse>(account))); }
public async Task <IHttpActionResult> ResetPassword([FromBody] AccountResetPasswordInfo info, CancellationToken token) { CustomTrace.TraceInformation($"Account.ResetPassword AccountName={info.AccountName}"); var account = await this.Database.Accounts.GetSingleAsync(a => a.AccountName == info.AccountName, token); if (account == null) { throw new UCenterException(UCenterErrorCode.AccountNotExist); } if (!EncryptHashManager.VerifyHash(info.SuperPassword, account.SuperPassword)) { await this.RecordLogin( account, UCenterErrorCode.AccountLoginFailedPasswordNotMatch, "The super password provided is incorrect", token); throw new UCenterException(UCenterErrorCode.AccountLoginFailedPasswordNotMatch); } account.Password = EncryptHashManager.ComputeHash(info.Password); await this.Database.Accounts.UpsertAsync(account, token); await this.RecordLogin(account, UCenterErrorCode.Success, "Reset password successfully.", token); return(this.CreateSuccessResult(this.ToResponse <AccountResetPasswordResponse>(account))); }
public async Task <IActionResult> GuestAccess([FromBody] GuestAccessInfo info, CancellationToken token) { if (info == null) { throw new UCenterException(UCenterErrorCode.DeviceInfoNull); } if (string.IsNullOrEmpty(info.AppId)) { throw new UCenterException(UCenterErrorCode.DeviceInfoNull); } EnsureDeviceInfo(info.Device); AccountEntity accountEntity; string guestDeviceId = $"{info.AppId}_{info.Device.Id}"; var guestDeviceEntity = await this.Database.GuestDevices.GetSingleAsync(guestDeviceId, token); if (guestDeviceEntity == null) { accountEntity = new AccountEntity() { Id = Guid.NewGuid().ToString(), AccountName = Guid.NewGuid().ToString(), AccountType = AccountType.Guest, AccountStatus = AccountStatus.Active, Token = EncryptHashManager.GenerateToken() }; await this.Database.Accounts.InsertAsync(accountEntity, token); guestDeviceEntity = new GuestDeviceEntity() { Id = $"{info.AppId}_{info.Device.Id}", AccountId = accountEntity.Id, AppId = info.AppId, Device = info.Device }; await this.Database.GuestDevices.InsertAsync(guestDeviceEntity, token); await this.TraceAccountEvent(accountEntity, "GuestRegister", info.Device, token : token); } else { accountEntity = await this.Database.Accounts.GetSingleAsync(guestDeviceEntity.AccountId, token); await this.TraceAccountEvent(accountEntity, "GuestLogin", info.Device, token : token); } await LogDeviceInfo(info.Device, token); var response = new GuestAccessResponse { AccountId = accountEntity.Id, AccountName = accountEntity.AccountName, AccountType = accountEntity.AccountType, Token = accountEntity.Token }; return(this.CreateSuccessResult(response)); }
public async Task <IHttpActionResult> GuestLogin([FromBody] AccountLoginInfo info, CancellationToken token) { CustomTrace.TraceInformation("Account.GuestLogin"); var r = new Random(); string accountNamePostfix = r.Next(0, 1000000).ToString("D6"); string accountName = $"uc_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}_{accountNamePostfix}"; string accountToken = EncryptHashManager.GenerateToken(); string password = Guid.NewGuid().ToString(); var account = new AccountEntity { Id = Guid.NewGuid().ToString(), AccountName = accountName, IsGuest = true, Password = EncryptHashManager.ComputeHash(password), Token = EncryptHashManager.GenerateToken() }; await this.Database.Accounts.InsertAsync(account, token); var response = new AccountGuestLoginResponse { AccountId = account.Id, AccountName = accountName, Token = accountToken, Password = password }; return(this.CreateSuccessResult(response)); }
public async Task <IHttpActionResult> Login([FromBody] AccountLoginInfo info, CancellationToken token) { CustomTrace.TraceInformation($"Account.Login AccountName={info.AccountName}"); var account = await this.Database.Accounts.GetSingleAsync(a => a.AccountName == info.AccountName, token); if (account == null) { throw new UCenterException(UCenterErrorCode.AccountNotExist); } if (!EncryptHashManager.VerifyHash(info.Password, account.Password)) { await this.RecordLogin( account, UCenterErrorCode.AccountLoginFailedPasswordNotMatch, "The account name and password do not match", token); throw new UCenterException(UCenterErrorCode.AccountLoginFailedPasswordNotMatch); } account.LastLoginDateTime = DateTime.UtcNow; account.Token = EncryptHashManager.GenerateToken(); await this.Database.Accounts.UpsertAsync(account, token); await this.RecordLogin(account, UCenterErrorCode.Success, token : token); return(this.CreateSuccessResult(this.ToResponse <AccountLoginResponse>(account))); }
public void TestEncryptAndCompare() { string password = Guid.NewGuid().ToString(); var hash = EncryptHashManager.ComputeHash(password); Assert.IsFalse(EncryptHashManager.VerifyHash(Guid.NewGuid().ToString(), hash)); Assert.IsTrue(EncryptHashManager.VerifyHash(password, hash)); }
public void TestEncryptAndCompare() { string password = Guid.NewGuid().ToString(); var hash = EncryptHashManager.ComputeHash(password); CustomTrace.TraceInformation("Hash code is: {0}", hash); Assert.IsFalse(EncryptHashManager.VerifyHash(Guid.NewGuid().ToString(), hash)); Assert.IsTrue(EncryptHashManager.VerifyHash(password, hash)); }
public async Task <IActionResult> WeChatLogin(AccountWeChatOAuthInfo info, CancellationToken token) { string appId = "Todo_AppId"; string appSecret = "Todo_AppSecret"; string code = "Todo_Code"; string grantType = "authorization_code"; string url = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type={grantType}"; using (var httpClient = new HttpClient()) { var response = await httpClient.GetAsync(url, token); var accessToken = await response.Content.ReadAsAsync <OAuthTokenResponse>(token); if (accessToken != null && !string.IsNullOrEmpty(accessToken.AccessToken)) { var weChatAccountEntity = await this.Database.WeChatAccounts.GetSingleAsync(a => a.OpenId == accessToken.OpenId, token); if (weChatAccountEntity == null) { weChatAccountEntity = new WeChatAccountEntity() { AccountId = info.AccountId, AppId = info.AppId, OpenId = accessToken.OpenId, UnionId = accessToken.UnionId }; await this.Database.WeChatAccounts.InsertAsync(weChatAccountEntity, token); var accountEntity = new AccountEntity() { Id = Guid.NewGuid().ToString(), AccountName = Guid.NewGuid().ToString(), AccountType = AccountType.Guest, AccountStatus = AccountStatus.Active, Token = EncryptHashManager.GenerateToken() }; await this.Database.Accounts.InsertAsync(accountEntity, token); return(this.CreateSuccessResult(accountEntity)); } else { var accountEntity = await this.Database.Accounts.GetSingleAsync(a => a.Id == weChatAccountEntity.AccountId, token); await AccountLoginAsync(accountEntity, token); return(this.CreateSuccessResult(accountEntity)); } } throw new UCenterException(UCenterErrorCode.AccountOAuthTokenUnauthorized, "OAuth Token Unauthorized"); } }
public async Task <IHttpActionResult> Login([FromBody] AccountLoginInfo info) { Logger.Info($"Account.Login AccountName={info.AccountName}"); var accountResourceByName = await this.DatabaseContext.Bucket.GetByEntityIdSlimAsync <AccountResourceEntity>( AccountResourceEntity.GenerateResourceId(AccountResourceType.AccountName, info.AccountName), false); AccountEntity account = null; if (accountResourceByName != null) { // this means the temp value still exists, we can directly get the account by account id. account = await this.DatabaseContext.Bucket.GetByEntityIdSlimAsync <AccountEntity>( accountResourceByName.AccountId); } else { // this means the temp value not exists any more, meanwhile, it have passed a period after the account created // so the index should be already created and we can query the entity by query string account = await this.DatabaseContext.Bucket.FirstOrDefaultAsync <AccountEntity>( a => a.AccountName == info.AccountName); } if (account == null) { throw new UCenterException(UCenterErrorCode.AccountNotExist); } if (!EncryptHashManager.VerifyHash(info.Password, account.Password)) { await this.RecordLogin(account, UCenterErrorCode.AccountLoginFailedPasswordNotMatch, "The account name and password do not match"); throw new UCenterException(UCenterErrorCode.AccountLoginFailedPasswordNotMatch); } account.LastLoginDateTime = DateTime.UtcNow; account.Token = EncryptHashManager.GenerateToken(); await this.DatabaseContext.Bucket.UpsertSlimAsync(account); await this.RecordLogin(account, UCenterErrorCode.Success); return(CreateSuccessResult(ToResponse <AccountLoginResponse>(account))); }
public async Task <IHttpActionResult> ResetPassword([FromBody] AccountResetPasswordInfo info) { Logger.Info($"Account.ResetPassword AccountName={info.AccountId}"); var account = await GetAndVerifyAccount(info.AccountId); if (!EncryptHashManager.VerifyHash(info.SuperPassword, account.SuperPassword)) { await this.RecordLogin(account, UCenterErrorCode.AccountLoginFailedPasswordNotMatch, "The super password provided is incorrect"); throw new UCenterException(UCenterErrorCode.AccountLoginFailedPasswordNotMatch); } account.Password = EncryptHashManager.ComputeHash(info.Password); await this.DatabaseContext.Bucket.UpsertSlimAsync(account); await this.RecordLogin(account, UCenterErrorCode.Success, "Reset password successfully."); return(CreateSuccessResult(ToResponse <AccountResetPasswordResponse>(account))); }
/// <summary> /// Get client IP area. /// </summary> /// <param name="token">Indicating the cancellation token.</param> /// <returns>Async task.</returns> //[HttpGet] //[Route("api/accounts/ip")] //public IActionResult GetClientIp(CancellationToken token) //{ // string ipAddress = IPHelper.GetClientIpAddress(Request); // return this.CreateSuccessResult(ipAddress); //} /// <summary> /// Generate token and login account /// </summary> /// <param name="token">Indicating the cancellation token.</param> /// <returns>Async task.</returns> private async Task AccountLoginAsync(AccountEntity accountEntity, CancellationToken token) { if (accountEntity.AccountStatus == AccountStatus.Disabled) { await this.TraceAccountErrorAsync( accountEntity, UCenterErrorCode.AccountDisabled, "The account is disabled", token); throw new UCenterException(UCenterErrorCode.AccountDisabled); } accountEntity.Token = EncryptHashManager.GenerateToken(); accountEntity.LastLoginDateTime = DateTime.UtcNow; var filter = Builders <AccountEntity> .Filter.Where(e => e.Id == accountEntity.Id); var update = Builders <AccountEntity> .Update .Set("Token", accountEntity.Token) .Set("LastLoginDateTime", accountEntity.LastLoginDateTime); await this.Database.Accounts.UpdateOneAsync <AccountEntity>(accountEntity, filter, update, token); }
public async Task <IHttpActionResult> Register([FromBody] AccountRegisterRequestInfo info, CancellationToken token) { this.Logger.Info($"Account.Register AccountName={info.AccountName}"); var removeTempsIfError = new List <AccountResourceEntity>(); var error = false; try { var account = await DatabaseContext.Bucket.FirstOrDefaultAsync <AccountEntity>( a => a.AccountName == info.AccountName, false); if (account != null) { throw new UCenterException(UCenterErrorCode.AccountRegisterFailedAlreadyExist); } account = new AccountEntity { AccountName = info.AccountName, IsGuest = false, Name = info.Name, IdentityNum = info.IdentityNum, Password = EncryptHashManager.ComputeHash(info.Password), SuperPassword = EncryptHashManager.ComputeHash(info.SuperPassword), PhoneNum = info.PhoneNum, Sex = info.Sex, CreatedDateTime = DateTime.UtcNow }; if (!string.IsNullOrEmpty(account.AccountName)) { var namePointer = new AccountResourceEntity(account, AccountResourceType.AccountName); await this.DatabaseContext.Bucket.InsertSlimAsync(namePointer); removeTempsIfError.Add(namePointer); } if (!string.IsNullOrEmpty(account.PhoneNum)) { var phonePointer = new AccountResourceEntity(account, AccountResourceType.Phone); await this.DatabaseContext.Bucket.InsertSlimAsync(phonePointer); removeTempsIfError.Add(phonePointer); } else if (!string.IsNullOrEmpty(account.Email)) { var emailPointer = new AccountResourceEntity(account, AccountResourceType.Email); await this.DatabaseContext.Bucket.InsertSlimAsync(emailPointer); removeTempsIfError.Add(emailPointer); } // set the default profiles account.ProfileImage = await this.storageContext.CopyBlobAsync( account.Sex == Sex.Female ?this.settings.DefaultProfileImageForFemaleBlobName : this.settings.DefaultProfileImageForMaleBlobName, this.settings.ProfileImageForBlobNameTemplate.FormatInvariant(account.Id), token); account.ProfileThumbnail = await this.storageContext.CopyBlobAsync( account.Sex == Sex.Female ?this.settings.DefaultProfileThumbnailForFemaleBlobName : this.settings.DefaultProfileThumbnailForMaleBlobName, this.settings.ProfileThumbnailForBlobNameTemplate.FormatInvariant(account.Id), token); await this.DatabaseContext.Bucket.InsertSlimAsync(account); return(CreateSuccessResult(ToResponse <AccountRegisterResponse>(account))); } catch (Exception ex) { this.Logger.Info($"Account.Register Exception:AccoundName={info.AccountName}"); this.Logger.Info(ex.ToString()); error = true; if (ex is CouchBaseException) { var status = (ex as CouchBaseException).Result as IDocumentResult <AccountResourceEntity>; if (status != null) { throw new UCenterException(UCenterErrorCode.AccountRegisterFailedAlreadyExist, ex); } } throw; } finally { if (error) { foreach (var item in removeTempsIfError) { this.DatabaseContext.Bucket.Remove(item.ToDocument()); } } } }
public async Task <IHttpActionResult> Register([FromBody] AccountRegisterRequestInfo info, CancellationToken token) { CustomTrace.TraceInformation($"Account.Register AccountName={info.AccountName}"); if (!ValidateAccountName(info.AccountName)) { // TODO: Change to AccountRegisterFailedInvalidName in next client refresh throw new UCenterException(UCenterErrorCode.AccountRegisterFailedAlreadyExist); } var removeTempsIfError = new List <KeyPlaceholderEntity>(); var error = false; try { var account = await this.Database.Accounts.GetSingleAsync(a => a.AccountName == info.AccountName, token); if (account != null) { throw new UCenterException(UCenterErrorCode.AccountRegisterFailedAlreadyExist); } account = new AccountEntity { Id = Guid.NewGuid().ToString(), AccountName = info.AccountName, IsGuest = false, Name = info.Name, Email = info.Email, IdentityNum = info.IdentityNum, Password = EncryptHashManager.ComputeHash(info.Password), SuperPassword = EncryptHashManager.ComputeHash(info.SuperPassword), PhoneNum = info.PhoneNum, Sex = info.Sex }; var placeholders = new[] { this.GenerateKeyPlaceholder(account.AccountName, KeyType.Name, account.Id, account.AccountName), this.GenerateKeyPlaceholder(account.PhoneNum, KeyType.Phone, account.Id, account.AccountName), this.GenerateKeyPlaceholder(account.Email, KeyType.Email, account.Id, account.AccountName) }; foreach (var placeholder in placeholders) { if (!string.IsNullOrEmpty(placeholder.Name)) { await this.Database.KeyPlaceholders.InsertAsync(placeholder, token); removeTempsIfError.Add(placeholder); } } // set the default profiles account.ProfileImage = await this.storageContext.CopyBlobAsync( account.Sex == Sex.Female?this.settings.DefaultProfileImageForFemaleBlobName : this.settings.DefaultProfileImageForMaleBlobName, this.settings.ProfileImageForBlobNameTemplate.FormatInvariant(account.Id), token); account.ProfileThumbnail = await this.storageContext.CopyBlobAsync( account.Sex == Sex.Female ?this.settings.DefaultProfileThumbnailForFemaleBlobName : this.settings.DefaultProfileThumbnailForMaleBlobName, this.settings.ProfileThumbnailForBlobNameTemplate.FormatInvariant(account.Id), token); await this.Database.Accounts.InsertAsync(account, token); return(this.CreateSuccessResult(this.ToResponse <AccountRegisterResponse>(account))); } catch (Exception ex) { CustomTrace.TraceError(ex, "Account.Register Exception:AccoundName={info.AccountName}"); error = true; if (ex is MongoWriteException) { var mex = ex as MongoWriteException; if (mex.WriteError.Category == ServerErrorCategory.DuplicateKey) { throw new UCenterException(UCenterErrorCode.AccountRegisterFailedAlreadyExist, ex); } } throw; } finally { if (error) { try { foreach (var item in removeTempsIfError) { this.Database.KeyPlaceholders.DeleteAsync(item, token).Wait(token); } } catch (Exception ex) { CustomTrace.TraceError(ex, "Error to remove placeholder"); } } } }
public async Task <IActionResult> WeChatLogin([FromBody] AccountWeChatOAuthInfo info, CancellationToken token) { // info.AppId目前传值不正确,应等于settings.WechatAppId // 后续应当根据info.AppId去查找对应WechatAppSecret logger.LogInformation("WeChatLogin AppId=" + info.AppId); logger.LogInformation("WeChatLogin AppId=" + settings.WechatAppId); logger.LogInformation("WeChatLogin Code=" + info.Code); OAuthAccessTokenResult access_token_result = null; try { access_token_result = await OAuthApi.GetAccessTokenAsync( settings.WechatAppId, settings.WechatAppSecret, info.Code); } catch (Exception ex) { logger.LogError(ex.ToString()); throw new UCenterException(UCenterErrorCode.AccountOAuthTokenUnauthorized); } if (access_token_result == null || access_token_result.errcode != 0) { logger.LogError("GetAccessTokenAsync失败"); throw new UCenterException(UCenterErrorCode.AccountOAuthTokenUnauthorized); } OAuthUserInfo user_info = null; try { user_info = await OAuthApi.GetUserInfoAsync( access_token_result.access_token, access_token_result.openid); } catch (Exception ex) { logger.LogError(ex.ToString()); throw new UCenterException(UCenterErrorCode.AccountOAuthTokenUnauthorized); } if (user_info == null) { logger.LogError("OAuthUserInfo为空"); throw new UCenterException(UCenterErrorCode.AccountOAuthTokenUnauthorized); } logger.LogInformation("OpenId=" + user_info.openid); logger.LogInformation("NickName=" + user_info.nickname); logger.LogInformation("Sex=" + user_info.sex); logger.LogInformation("Province=" + user_info.province); logger.LogInformation("City=" + user_info.city); logger.LogInformation("Country=" + user_info.country); logger.LogInformation("Headimgurl=" + user_info.headimgurl); logger.LogInformation("Unionid=" + user_info.unionid); if (user_info.privilege != null) { foreach (var i in user_info.privilege) { if (i != null) { logger.LogInformation("Privilege=" + i); } } } bool need_update_nickname = false; bool need_update_icon = false; // 查找AccountWechat var acc_wechat = await this.Database.AccountWechat.GetSingleAsync( a => a.Unionid == user_info.unionid && a.OpenId == user_info.openid && a.AppId == settings.WechatAppId, token); // 创建AccountWechat if (acc_wechat == null) { acc_wechat = new AccountWechatEntity() { Id = Guid.NewGuid().ToString(), AccountId = Guid.NewGuid().ToString(), Unionid = user_info.unionid, OpenId = user_info.openid, AppId = settings.WechatAppId, NickName = user_info.nickname, Gender = (Gender)user_info.sex, Province = user_info.province, City = user_info.city, Country = user_info.country, Headimgurl = user_info.headimgurl }; await this.Database.AccountWechat.InsertAsync(acc_wechat, token); need_update_nickname = true; need_update_icon = true; } else { if (acc_wechat.Headimgurl != user_info.headimgurl) { acc_wechat.Headimgurl = user_info.headimgurl; need_update_icon = true; } if (acc_wechat.NickName != user_info.nickname) { acc_wechat.NickName = user_info.nickname; need_update_nickname = true; } if (need_update_icon || need_update_nickname) { await this.Database.AccountWechat.UpsertAsync(acc_wechat, token); } } // 查找Account var acc = await this.Database.Accounts.GetSingleAsync( acc_wechat.AccountId, token); // 创建Account if (acc == null) { acc = new AccountEntity() { Id = acc_wechat.AccountId, AccountName = Guid.NewGuid().ToString(), AccountType = AccountType.NormalAccount, AccountStatus = AccountStatus.Active, //Password = EncryptHelper.ComputeHash(info.Password), //SuperPassword = EncryptHelper.ComputeHash(info.SuperPassword), Token = EncryptHashManager.GenerateToken(), Gender = acc_wechat.Gender, Identity = string.Empty, Phone = string.Empty, Email = string.Empty }; await this.Database.Accounts.InsertAsync(acc, token); need_update_nickname = true; need_update_icon = true; } // 微信头像覆盖Acc头像 if (need_update_icon && !string.IsNullOrEmpty(user_info.headimgurl)) { //logger.LogInformation("微信头像覆盖Acc头像,Headimgurl={0}", acc_wechat.Headimgurl); await DownloadWechatHeadIcon(user_info.headimgurl, acc.Id, token); acc.ProfileImage = user_info.headimgurl; await this.Database.Accounts.UpsertAsync(acc, token); } string current_nickname = string.Empty; var app = UCenterContext.Instance.CacheAppEntity.GetAppEntityByWechatAppId(settings.WechatAppId); var data_id = $"{app.Id}_{acc.Id}"; var account_data = await this.Database.AppAccountDatas.GetSingleAsync(data_id, token); if (account_data != null) { var m = JsonConvert.DeserializeObject <Dictionary <string, string> >(account_data.Data); if (m.ContainsKey("nick_name")) { current_nickname = m["nick_name"]; } // 微信昵称覆盖Acc昵称 if (current_nickname != acc_wechat.NickName && !string.IsNullOrEmpty(acc_wechat.NickName)) { m["nick_name"] = acc_wechat.NickName; account_data.Data = JsonConvert.SerializeObject(m); await this.Database.AppAccountDatas.UpsertAsync(account_data, token); } } else { Dictionary <string, string> m = new Dictionary <string, string>(); m["nick_name"] = acc_wechat.NickName; account_data = new AppAccountDataEntity { Id = data_id, AppId = app.Id, AccountId = acc.Id, Data = JsonConvert.SerializeObject(m) }; await this.Database.AppAccountDatas.UpsertAsync(account_data, token); } return(this.CreateSuccessResult(this.ToResponse <AccountLoginResponse>(acc))); }